refactor: replace Wingbits (paid) with hexdb.io (free) for aircraft lookups

hexdb.io provides ICAO hex aircraft details with no API key required,
eliminating the 30-day trial limitation of Wingbits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Marc Shade
2026-02-23 11:12:09 -05:00
co-authored by Claude Opus 4.6
parent 3131ccbcdc
commit a4d2b546a3
2 changed files with 10 additions and 16 deletions
+2 -2
View File
@@ -205,7 +205,7 @@ TOOLS: list[Tool] = [
),
Tool(
name="intel_aircraft_details",
description="Get aircraft details from Wingbits by ICAO24 hex code. Requires WINGBITS_API_KEY.",
description="Get aircraft details from hexdb.io by ICAO24 hex code (free, no API key).",
inputSchema={
"type": "object",
"properties": {
@@ -576,7 +576,7 @@ async def _dispatch(name: str, arguments: dict[str, Any]) -> Any:
"economic": ["eia", "fred", "world-bank"],
"natural": ["usgs", "nasa-firms"],
"conflict": ["acled", "ucdp", "hdx"],
"military": ["opensky", "wingbits"],
"military": ["opensky", "hexdb"],
"infrastructure": ["cloudflare-radar", "nga-msi"],
"maritime": ["nga-msi"],
"climate": ["open-meteo"],
+8 -14
View File
@@ -1,7 +1,7 @@
"""Military aviation tracking source for world-intel-mcp.
Provides real-time military aircraft tracking via OpenSky Network and
aircraft detail lookups via the Wingbits API.
aircraft detail lookups via hexdb.io (free, no API key).
"""
import asyncio
@@ -19,7 +19,7 @@ logger = logging.getLogger("world-intel-mcp.sources.military")
# ---------------------------------------------------------------------------
_OPENSKY_STATES_URL = "https://opensky-network.org/api/states/all"
_WINGBITS_BASE_URL = "https://api.wingbits.com/v1/aircraft"
_HEXDB_BASE_URL = "https://hexdb.io/api/v1/aircraft"
# ICAO hex prefix ranges known to be allocated to military operators.
MILITARY_ICAO_PREFIXES = [
@@ -236,7 +236,7 @@ async def fetch_theater_posture(fetcher: Fetcher) -> dict:
async def fetch_aircraft_details(fetcher: Fetcher, icao24: str) -> dict:
"""Look up detailed aircraft information from the Wingbits API.
"""Look up detailed aircraft information from hexdb.io (free, no API key).
Args:
fetcher: Shared HTTP fetcher with caching and circuit breaking.
@@ -245,31 +245,25 @@ async def fetch_aircraft_details(fetcher: Fetcher, icao24: str) -> dict:
Returns:
Dict with aircraft detail payload, source, and timestamp.
"""
api_key = os.environ.get("WINGBITS_API_KEY")
if not api_key:
return {"error": "WINGBITS_API_KEY not configured"}
url = f"{_WINGBITS_BASE_URL}/{icao24}"
headers = {"X-API-Key": api_key}
url = f"{_HEXDB_BASE_URL}/{icao24}"
data = await fetcher.get_json(
url=url,
source="wingbits",
source="hexdb",
cache_key=f"military:aircraft:{icao24}",
cache_ttl=3600,
headers=headers,
)
if data is None:
logger.warning("Wingbits returned no data for icao24=%s", icao24)
logger.warning("hexdb.io returned no data for icao24=%s", icao24)
return {
"aircraft": {},
"source": "wingbits",
"source": "hexdb",
"timestamp": _utc_now_iso(),
}
return {
"aircraft": data,
"source": "wingbits",
"source": "hexdb",
"timestamp": _utc_now_iso(),
}