lotw-mcp
Read-only MCP server for querying ARRL Logbook of The World (LoTW) data.
Query confirmed QSLs with band, mode, callsign, DXCC, and date filters.
Query uploaded QSOs, confirmed and unconfirmed, with band/mode/date filters.
Retrieve DXCC award credits from LoTW confirmations.
Download LoTW logs as ADIF text, optionally filtering to confirmed QSLs only.
Check whether a callsign uses LoTW and when they last uploaded, using public cached data with no auth.
Get lotw-mcp service version and upstream LoTW schema version for fleet alignment.
Uses qso-graph-auth personas for authenticated LoTW tools; uploads are out of scope.
Enables querying ARRL Logbook of The World (LoTW) confirmations, uploaded QSOs, DXCC credits, and user activity through GitHub Copilot.
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., "@lotw-mcpHow many LoTW confirmations did I get this month?"
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.
lotw-mcp
MCP server for ARRL Logbook of The World (LoTW) — query confirmations, uploaded QSOs, DXCC credits, and user activity through any MCP-compatible AI assistant.
Part of the qso-graph project. Read-only — uploads require TQSL digital signatures and are out of scope.
Install
uvx lotw-mcp # run it; nothing to installRelated MCP server: hamqth-mcp
Tools
Tool | Auth | Description |
| Yes | Query confirmed QSLs with band/mode/call/date filters |
| Yes | Query all uploaded QSOs (confirmed and unconfirmed) |
| Yes | DXCC award credits from LoTW confirmations |
| Yes | Download QSOs as ADIF file |
| No | Check if a callsign uses LoTW and when they last uploaded |
| No | Service version + upstream LoTW schema version (fleet identity attestation) |
Quick Start
1. Set up credentials
lotw-mcp uses qso-graph-auth personas for credential management:
# Install qso-graph-auth if you haven't
uv tool install qso-graph-auth
# A persona (your callsign and the dates it covers), then LoTW for it
qso-graph-auth persona add --name ki7mt --callsign KI7MT --start 2020-01-01
qso-graph-auth provider enable ki7mt lotw
qso-graph-auth creds set ki7mt lotw # asks for your username, then your password (hidden)All three steps are needed: without provider enable, the server reports that the persona has no lotw ref.
Note: The LoTW login is usually your callsign but not always. Pre-Sept 2019 accounts may require lowercase passwords. Avoid special characters in passwords.
2. Configure your MCP client
Claude Desktop
Add to claude_desktop_config.json (~/Library/Application Support/Claude/ on macOS, %APPDATA%\Claude\ on Windows):
{
"mcpServers": {
"lotw": {
"command": "uvx",
"args": ["lotw-mcp"]
}
}
}Claude Code
Add to .claude/settings.json:
{
"mcpServers": {
"lotw": {
"command": "uvx",
"args": ["lotw-mcp"]
}
}
}ChatGPT Desktop
{
"mcpServers": {
"lotw": {
"command": "uvx",
"args": ["lotw-mcp"]
}
}
}Cursor
Add to .cursor/mcp.json (project-level) or ~/.cursor/mcp.json (global):
{
"mcpServers": {
"lotw": {
"command": "uvx",
"args": ["lotw-mcp"]
}
}
}VS Code / GitHub Copilot
Add to .vscode/mcp.json in your workspace:
{
"servers": {
"lotw": {
"command": "uvx",
"args": ["lotw-mcp"]
}
}
}Gemini CLI
Add to ~/.gemini/settings.json (global) or .gemini/settings.json (project):
{
"mcpServers": {
"lotw": {
"command": "uvx",
"args": ["lotw-mcp"]
}
}
}3. Ask questions
"How many LoTW confirmations did I get this month?"
"Show me all unconfirmed 20m FT8 QSOs uploaded to LoTW in the last 90 days"
"What DXCC credits do I have on 40m CW?"
"Does JA1ABC use LoTW? When did they last upload?"
Public Tool
lotw_user_activity works without any credentials. It uses the public LoTW user activity CSV, cached locally for 7 days.
Testing Without Credentials
Set the mock environment variable:
LOTW_MCP_MOCK=1 lotw-mcpPerformance Notes
LoTW can be slow (30-60s for large queries). lotw-mcp uses 120s timeouts. Use date filters (since, start_date) to limit result sets.
MCP Inspector
lotw-mcp --transport streamable-http --port 8004Development
git clone https://github.com/qso-graph/lotw-mcp.git
cd lotw-mcp
uv sync --group dev
uv run pytestLicense
GPL-3.0-or-later
Available Tools
6 toolsget_version_infoGet Version InfoARead-onlyIdempotent
Get lotw-mcp service version and upstream LoTW schema version.
Returns the running PyPI version of lotw-mcp and the ARRL LoTW ADIF/CSV export schema in use. Use this to confirm fleet alignment across MCP deployments — agents can compare service_version and spec_version across servers to detect drift without going outside the MCP protocol.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false, so the safety profile is known. The description adds useful behavioral context by explaining that it returns both service_version and spec_version and is intended for cross-server drift detection. It does not mention auth or rate limits, but none are implied for a version lookup.
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-loaded with what it gets, followed by return content and intended use. Every sentence adds value with no repetition or 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 a zero-parameter, read-only version tool with an output schema and full annotations, the description is complete. It explains what is returned and why an agent would call it, while the output schema handles return structure details.
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 tool has zero parameters, so parameter semantics are not a meaningful gap and the baseline is 4. The description correctly does not invent parameter behavior. The schema is trivially complete with additionalProperties=false.
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 and resource: it gets the lotw-mcp service version and the upstream LoTW schema version. This clearly distinguishes it from the sibling data-oriented lotw_* tools. An agent can immediately tell this is metadata/diagnostic, not a QSO or confirmation query.
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 states a concrete use case: confirm fleet alignment by comparing service_version and spec_version across deployments to detect drift. There is no explicit when-not guidance, but no sibling tool covers this metadata need, so the usage context is sufficiently clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lotw_confirmationsLotw ConfirmationsBRead-onlyIdempotent
Query confirmed QSL records from LoTW.
| Name | Required | Description | Default |
|---|---|---|---|
| band | No | Filter by ADIF band (e.g., '20M'). | |
| dxcc | No | Filter by DXCC entity code. | |
| mode | No | Filter by ADIF mode (e.g., 'FT8'). | |
| since | No | QSLs received since this date (YYYY-MM-DD). Default: last 30 days. | |
| detail | No | Include QSL station location data (default true). | |
| persona | Yes | Persona name configured in adif-mcp. | |
| callsign | No | Filter by worked station callsign. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered. The description only adds the 'confirmed records' qualifier, with no mention of return volume, pagination, or LoTW auth requirements at a behavior level.
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?
A single front-loaded sentence with no waste. It is arguably too terse for a 7-parameter tool, but nothing is redundant or buried.
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 an output schema present and full parameter descriptions, the core call mechanics are covered by structured fields. However, the description never clarifies what 'confirmed' means operationally or how results differ from lotw_qsos, leaving a conceptual gap an agent must resolve.
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%, including filter formats like ADIF band/mode and the 'last 30 days' default, so the schema carries parameter meaning. The description adds no additional parameter guidance beyond what is structured.
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?
States a specific verb ('Query') and resource ('confirmed QSL records') scoped to LoTW. The word 'confirmed' implicitly distinguishes it from lotw_qsos, though the sibling is not named, so an agent must infer the split.
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 indication of when to prefer this over lotw_qsos or lotw_user_activity, and no prerequisites or exclusion conditions are given. The agent has to infer usage from the tool name and sibling list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lotw_downloadLotw DownloadARead-onlyIdempotent
Download your complete LoTW log as raw ADIF text.
Returns the .adi file content — save to disk for import into your logger. Set qsl_only=True for confirmed QSLs only. Omit 'since' for full history. Warning: large logs may take 30-60 seconds (LoTW is slow).
| Name | Required | Description | Default |
|---|---|---|---|
| band | No | Filter by band (e.g., '20M'). | |
| mode | No | Filter by mode (e.g., 'FT8'). | |
| since | No | Only records since this date (YYYY-MM-DD). Omit for full history. | |
| persona | Yes | Persona name configured in adif-mcp. | |
| qsl_only | No | Only return confirmed QSLs (default: all uploaded QSOs). |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this as a safe, read-only, idempotent, non-destructive operation. The description adds meaningful behavioral context beyond that: it returns .adi file content that should be saved to disk, and large downloads may take 30-60 seconds because LoTW is slow.
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 short, front-loaded with the core action and return format, then adds the key parameter hints and performance warning. Every sentence carries useful information without unnecessary 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?
Given the rich annotations, 100% schema coverage, and existing output schema, the description supplies the remaining practical context an agent needs: raw ADIF output, save-to-disk expectation, QSL filtering behavior, full-history default, and a performance warning. It is complete 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 parameters are already documented in the schema. The description reinforces the semantics of qsl_only and since, but mostly repeats schema-level meaning and does not add extra detail for band, mode, or persona.
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: downloading the complete LoTW log as raw ADIF text, and it clarifies the return format as .adi file content. It is clear enough to distinguish this from a general QSO query, but it does not explicitly route the agent away from siblings such as lotw_qsos or lotw_confirmations.
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 useful context for saving the raw ADIF file for import into a logger and notes that omitting 'since' returns full history. However, it does not explicitly say when to use this tool versus sibling tools like lotw_qsos or lotw_confirmations, so the usage guidance is implied rather than complete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lotw_dxcc_creditsLotw Dxcc CreditsBRead-onlyIdempotent
Query DXCC award credits from LoTW confirmations.
| Name | Required | Description | Default |
|---|---|---|---|
| entity | No | Optional DXCC entity code to filter by. | |
| persona | Yes | Persona name configured in adif-mcp. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, idempotentHint=true, and destructiveHint=false. The description adds only that the query concerns DXCC award credits derived from LoTW confirmations, without further behavioral context such as filtering behavior or result characteristics.
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 front-loaded sentence with no wasted words. It immediately states the operation and data source.
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?
An output schema exists and annotations cover the safety profile, so return values and read-only behavior need not be explained. However, the description lacks sibling differentiation and usage guidance, leaving an agent to infer when this tool is preferable to lotw_confirmations.
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 both the 'persona' and 'entity' parameters. The description does not add any parameter-specific meaning beyond what the schema provides, making the baseline of 3 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 and resource: 'Query DXCC award credits from LoTW confirmations.' This clearly communicates the tool's function, but it does not distinguish it from the sibling lotw_confirmations tool, which may also involve LoTW confirmations.
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 no guidance on when to use this tool versus alternatives such as lotw_confirmations or lotw_qsos. It only implies usage through the verb 'Query' and does not state exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lotw_qsosLotw QsosBRead-onlyIdempotent
Query all uploaded QSOs from LoTW (confirmed and unconfirmed).
| Name | Required | Description | Default |
|---|---|---|---|
| band | No | Filter by band (e.g., '20M'). | |
| mode | No | Filter by mode (e.g., 'FT8'). | |
| since | No | QSOs uploaded since this date (YYYY-MM-DD). Default: last 30 days. | |
| persona | Yes | Persona name configured in adif-mcp. | |
| end_date | No | QSO date range end (YYYY-MM-DD). | |
| start_date | No | QSO date range start (YYYY-MM-DD). |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, idempotentHint=true, and openWorldHint=true, so the safety profile is covered. The description adds that both confirmed and unconfirmed QSOs are included, but does not mention authentication/persona needs, pagination, or the default last-30-days window.
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?
A single front-loaded sentence with zero wasted words. It is appropriately sized for a tool whose detailed parameter semantics are fully covered by the schema.
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?
The output schema and annotations cover return shape and safety behavior, and the input schema documents all parameters. However, the description says 'all uploaded QSOs' while the schema notes a default last-30-days window, and the description gives no routing guidance among several sibling LoTW 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?
Schema description coverage is 100%, so all six parameters are already documented with examples and date formats. The description adds no parameter-level meaning beyond the schema, which is the expected baseline when schema coverage is complete.
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?
States a specific verb and resource: query uploaded QSOs from LoTW. The parenthetical 'confirmed and unconfirmed' gives useful scope and partially distinguishes it from lotw_confirmations, though it does not explicitly name sibling 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?
Provides no explicit guidance on when to use this tool versus lotw_confirmations, lotw_dxcc_credits, lotw_download, or lotw_user_activity. The query wording implies a general listing use case, but alternatives and exclusions are absent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lotw_user_activityLotw User ActivityARead-onlyIdempotent
Check if a callsign uses LoTW and when they last uploaded.
Public endpoint — no authentication required. Uses a locally cached copy of the LoTW user activity CSV (refreshed weekly).
| Name | Required | Description | Default |
|---|---|---|---|
| callsign | Yes | Callsign to check. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false. The description adds meaningful behavioral details beyond those annotations: no authentication is required and data comes from a weekly-refreshed local cache, so results may be up to a week stale.
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 short sentences, front-loaded with the purpose. Each sentence adds useful information: the lookup behavior, authentication status, and cache freshness.
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 read-only lookup with an output schema, the description covers the essentials: what it checks, that no auth is needed, and that cached data is refreshed weekly. Minor gaps remain around how exact the callsign match must be and when to prefer 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?
Schema description coverage is 100%, and the single parameter is already documented as 'Callsign to check.' The description does not add format, case-sensitivity, or other parameter semantics beyond what the schema provides, so 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?
States a specific verb and resource: check whether a callsign uses LoTW and when it last uploaded. The purpose is clear, but it does not explicitly distinguish itself from siblings like lotw_qsos or lotw_confirmations.
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?
Provides useful usage context: public endpoint, no authentication, and locally cached CSV refreshed weekly. However, it does not state when to choose this tool over sibling alternatives such as lotw_confirmations or lotw_qsos.
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.
6 tool updates
v0.3.3- First observed
get_version_info - First observed
lotw_confirmations - First observed
lotw_download - First observed
lotw_dxcc_credits - First observed
lotw_qsos - First observed
lotw_user_activity
TDQS
Scored across 6 tools
The tools mostly target distinct LoTW resources: confirmations, DXCC credits, all QSOs, raw log download, user activity, and version info. There is mild overlap between lotw_confirmations and lotw_qsos (confirmed subset vs all QSOs), but descriptions make the boundary clear.
Most tools use a consistent lotw_ domain prefix followed by a noun/action, e.g. lotw_confirmations, lotw_dxcc_credits, lotw_qsos. get_version_info deviates with a generic verb_noun pattern, but overall the set remains readable and predictable.
Six tools is well-scoped for a LoTW query/download server. Each tool covers a distinct capability without obvious filler or missing core operations.
The surface covers the main read-only LoTW workflows: QSO lookup, confirmations, DXCC credits, raw ADIF download, and callsign activity. Minor gaps exist for richer award queries (e.g. WAS/WAC) or detailed per-QSO inspection, but agents can work around them with the current tools.
Maintenance
Related MCP Connectors
- UnifAPIOAuthcom.unifapi
Hosted MCP server for live public-data APIs and Skills for AI agents.
MCP server for OnceAsk, the AI-native current-address layer for people and agents.
Official remote MCP server for Archivist AI TTRPG campaign memory: characters, sessions, and more.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Related MCP Servers
- AlicenseAqualityAmaintenanceAn MCP server for eQSL.cc that allows users to download incoming electronic QSL cards, verify specific contacts, and check Authenticity Guaranteed status. It enables natural language interaction with amateur radio logs and confirmation records through any MCP-compatible AI assistant.6464 PyPIGPL 3.0
- AlicenseAqualityAmaintenanceMCP server for HamQTH.com — callsign lookup, DX cluster spots, Reverse Beacon Network, DXCC resolution, and more through any MCP-compatible AI assistant.8586 PyPIGPL 3.0
- AlicenseAqualityAmaintenanceMCP server for QRZ.com — callsign lookups, DXCC entity resolution, and logbook queries through any MCP-compatible AI assistant.6575 PyPI4GPL 3.0
- AlicenseAqualityAmaintenanceEnables IOTA group lookup, island search, DXCC mapping, nearby groups, and programme statistics through any MCP-compatible AI assistant.7587 PyPIGPL 3.0