@cyanheads/faa-aircraft-registry-mcp-server
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., "@@cyanheads/faa-aircraft-registry-mcp-serverlook up N12345 registration"
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.
Public Hosted Server: https://faa-aircraft-registry.caseyjhand.com/mcp
Overview
The US civil aircraft registry, searchable offline from the FAA's Releasable Aircraft Database. Decode an N-number to its aircraft, engine, and registered owner; check whether it's active, deregistered, or reserved; and search by owner, make and model, state, or Mode S code.
Tools
Tool | Description |
| Decode one N-number to its full pre-joined active record — aircraft make/model, engine, year, airworthiness, registration status, Mode S code, and registered owner (when redaction is off). |
| Resolve an N-number across all three status files (active, deregistered, reserved) in priority order, returning a definitive |
| Search active registrations by owner name, make/model, exact manufacturer/model code, state, aircraft type, or Mode S code. |
| Search the aircraft reference table by manufacturer/model name, type, or category to discover manufacturer-model codes. |
| Decode a 6–7-character manufacturer/model/series code to aircraft specs — category, type, engine, seats, weight class, cruise speed, type-certificate data. |
Resources
Resource | Description |
| Full registration record for one N-number — the same decoded, pre-joined payload as |
Also reachable via faa_lookup_registration; search collections aren't exposed as resources.
Related MCP server: adsb.lol MCP Server
Capability reference
faa_lookup_registration tool
Accepts
N12345or12345; the leadingNis optionalReturns decoded aircraft, engine, and status fields as raw code plus label, and the Mode S code in octal and hex (hex is the ICAO 24-bit address)
Owner name and address appear only when
FAA_REDACT_OWNER_PII=false; otherwiseownerRedacted: trueErrors:
not_found(no active registration; tryfaa_get_registration_status),invalid_n_number
faa_get_registration_status tool
Checks the active, deregistered, and reserved files in that order
recordTypeisactive,deregistered,reserved, orunknown; a never-issued number returnsunknown, not an errorStatus facts only, no owner data
Error:
invalid_n_number
faa_search_registrations tool
Filters:
ownerName,makeModel,manufacturerModelCode,state,aircraftType,modeSCode; at least one required, combined with ANDlimit1–200 (default 25) withoffsetpaging; responses reporttotalCountandnextOffsetwhen truncatedEach result carries an N-number to pass to
faa_lookup_registrationErrors:
no_filters,invalid_code,invalid_state,invalid_mode_s_code,invalid_aircraft_type, andowner_search_disabled(owner-name search is off whileFAA_REDACT_OWNER_PIIis on)
faa_search_aircraft_types tool
Filters:
query(manufacturer/model name),aircraftType(1–9/H/O),category(1–3); at least one requiredReturns summaries with the code to pass to
faa_get_aircraft_typeorfaa_search_registrations.manufacturerModelCodelimit1–200 (default 25) withoffsetpaging; responses reporttotalCountandnextOffsetwhen truncatedErrors:
no_filters,invalid_aircraft_type,invalid_category
faa_get_aircraft_type tool
Accepts a 6–7-character uppercase alphanumeric manufacturer/model/series code; find codes with
faa_search_aircraft_typesReturns manufacturer, model, type, engine, category, seats, engines, weight class, cruise speed, and type-certificate data
weightClasskeeps the raw FAA string;weightClassLabeldecodes it when knownErrors:
not_found,invalid_code
faa://registration/{nNumber} resource
Same payload as
faa_lookup_registration;application/json, cached 1 hournNumberacceptsN12345or12345Errors:
not_found,invalid_n_number
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
FAA registry-specific:
Offline and keyless at runtime: queries hit a local SQLite + FTS5 index with no API key or rate limit
Daily index refresh under HTTP transport, aligned to the FAA's nightly re-release
Pre-joined records: one call returns decoded aircraft, engine, and status
Owner name and address are redacted by default, and owner-name search is disabled until
FAA_REDACT_OWNER_PII=falseMode S hex codes match the ICAO 24-bit addresses used by flight-tracking feeds
Agent-friendly output:
Coded fields carry both the raw FAA code and the decoded label
Capped search results flag
truncatedwithshownandcapFields the FAA leaves blank stay absent rather than filled in
recordTypeandownerRedactedlet callers branch on data
Getting started
Public Hosted Instance
A public instance is available at https://faa-aircraft-registry.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"faa-aircraft-registry-mcp-server": {
"type": "streamable-http",
"url": "https://faa-aircraft-registry.caseyjhand.com/mcp"
}
}
}Self-Hosted / Local
First run requires building the local index — see First-run setup below. The package does not ship the FAA data; until
mirror:inithas run once, queries fail with a clear "run mirror:init" error.
The Desktop MCPB includes Node's SQLite driver and its cross-platform prebuilts. Build the local index with the bundle's mirror CLI before querying.
Add the following to your MCP client configuration file:
{
"mcpServers": {
"faa-aircraft-registry-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/faa-aircraft-registry-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"FAA_MIRROR_PATH": "/path/to/faa-registry.db"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"faa-aircraft-registry-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/faa-aircraft-registry-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"FAA_MIRROR_PATH": "/path/to/faa-registry.db"
}
}
}
}Or with Docker (mount a volume at /usr/src/app/.mirror so the built index persists across containers — build it once with docker exec … bun run mirror:init):
{
"mcpServers": {
"faa-aircraft-registry-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-v", "faa-registry:/usr/src/app/.mirror",
"ghcr.io/cyanheads/faa-aircraft-registry-mcp-server:latest"
]
}
}
}For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcpFAA_MIRROR_PATH points the server at the index that mirror:init builds — set it to a persistent path so the index survives across runs. Owner PII is redacted by default; set FAA_REDACT_OWNER_PII=false only on a trusted local install to expose owner detail.
First-run setup
The FAA Releasable Aircraft Database is not bundled with the package — it is a public dataset (~70 MB compressed, refreshed daily by the FAA) that the operator downloads and indexes once before first use. Building the index produces a local SQLite file of a few hundred MB.
Build the index out-of-band (never on server startup — a full parse of ~1M rows must not block start). From a source checkout, run bun install && bun run build first. Then, from the checkout, installed package directory, or extracted MCPB directory, run the compiled commands below. Node and Bun both work; replace node with bun to use Bun's built-in SQLite. The Docker image supports bun run mirror:init, mirror:verify, and mirror:refresh.
# Build the local index from the live FAA download (idempotent, resumable)
FAA_MIRROR_PATH=/path/to/faa-registry.db node dist/cli/faa-mirror-init.js
# Verify it built (readiness + integrity check)
FAA_MIRROR_PATH=/path/to/faa-registry.db node dist/cli/faa-mirror-verify.js
# Rebuild from the latest FAA release (run on a schedule, or out-of-band for stdio)
FAA_MIRROR_PATH=/path/to/faa-registry.db node dist/cli/faa-mirror-refresh.jsKeep the path stable. Point
FAA_MIRROR_PATH(and the same env var in your MCP client config) at a persistent location so the built index is reused across runs. Default:.mirror/faa-registry.db.Daily refresh. Under HTTP transport the server schedules a daily
mirror:refreshaligned to the FAA's nightly re-release (~11:30 PM Central). If an interrupted rebuild leaves the index empty, queries fail loudly withServiceUnavailableuntil the rebuild succeeds. Under stdio, runmirror:refreshout-of-band (e.g. a cron job).Docker. The image ships the mirror CLI and a writable
.mirrordata directory owned by the runtime user. Mount a volume there and runmirror:initonce (e.g.docker exec <container> bun run mirror:init, or a one-shot init job against the shared volume) so the index persists across container restarts.Until the index exists, every query fails with a
ServiceUnavailableerror whose recovery hint points tomirror:init— there is no live API to fall back to, so the cold state surfaces loudly rather than returning empty results.
The source URL is overridable via FAA_DATABASE_URL (for a private or cached mirror); it is read only at ingest time, never per request.
Prerequisites
Bun v1.4 or higher (or Node.js v24+). Bun uses built-in
bun:sqlite; Node uses the includedbetter-sqlite3dependency, with bundled N-API prebuilts for macOS, Windows, and Linux (glibc/musl), on x64 and arm64.Disk space for the built index (a few hundred MB) at
FAA_MIRROR_PATH.Network access at
mirror:init/mirror:refreshtime to download the FAA ZIP. Not needed at query time.
Installation
For local development or self-hosting from source:
Clone the repository:
git clone https://github.com/cyanheads/faa-aircraft-registry-mcp-server.gitNavigate into the directory:
cd faa-aircraft-registry-mcp-serverInstall dependencies:
bun installCompile the server and build the index (see First-run setup):
bun run build
bun run mirror:initConfiguration
Variable | Description | Default |
| Redact owner name and address and disable owner-name search. Unset, empty, or malformed counts as |
|
| Path to the SQLite index file; use a persistent location. |
|
| Source URL for the FAA database ZIP, read only by | FAA registry ZIP |
| Transport: |
|
| Session mode: |
|
| Port for the HTTP server. |
|
| HTTP endpoint path where the MCP server is mounted. |
|
| Auth mode: |
|
| Log level (RFC 5424). |
|
| Directory for log files (Node.js only). |
|
| Log each failed tool call's arguments and result (cap: |
|
| Enable OpenTelemetry instrumentation. |
|
See .env.example for the full list of optional overrides.
Running the server
Local development
Build and run:
# One-time build bun run rebuild # Build the local index (see First-run setup) bun run mirror:init # Run the built server bun run start:stdio # or bun run start:httpRun checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest unit and integration tests bun run test:package # npm tarball + cleaned MCPB runtime checks bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t faa-aircraft-registry-mcp-server .
docker run --rm -e MCP_TRANSPORT_TYPE=http -p 3010:3010 \
-v faa-registry:/usr/src/app/.mirror faa-aircraft-registry-mcp-server
# Build the index once against the mounted volume:
docker run --rm -v faa-registry:/usr/src/app/.mirror faa-aircraft-registry-mcp-server bun run mirror:initThe Dockerfile defaults to HTTP transport with stateless sessions, ships the mirror:init/mirror:refresh/mirror:verify CLI, pre-creates a writable .mirror data directory owned by the runtime user (mount a volume there and run mirror:init once to build and persist the index), and logs to /var/log/faa-aircraft-registry-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Directory | Purpose |
|
|
| Server-specific environment variable parsing and validation with Zod. |
| Tool definitions ( |
| Resource definitions ( |
| Registry service — the SQLite + FTS5 mirror, ingester, decode maps, N-number normalizer, and the owner-PII redaction gate. |
| Mirror lifecycle CLI — compiled to |
| Unit and integration tests mirroring |
Development guide
See CLAUDE.md/AGENTS.md for development guidelines and architectural rules. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storageRegister new tools and resources via the barrels in
src/mcp-server/*/definitions/index.ts
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
The FAA Releasable Aircraft Database is a public-domain US Government work, published by the FAA Civil Aviation Registry. This project redistributes none of that data; operators download it directly from the FAA at install time.
This server cannot be deployed
Maintenance
Related MCP Connectors
Offline global aviation reference: airports, runways, navaids, frequencies from OurAirports.
Scrape the FAA Aircraft Registry by N-number — aircraft make, model, year, owner name, address, airw
FAA civil aircraft registry — resolve a US tail number (N-number) to its
Aircraft registry search, flight history, and analytics powered by ADS-B Exchange data.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides real-time aircraft tracking data from OpenSky Network combined with FAA aircraft registry information, enabling rich aviation queries that merge live flight positions with technical specifications.1MIT
- AlicenseNot gradedqualityDmaintenanceProvides AI assistants with real-time aircraft tracking, FAA registration, and OpenSky flight data through the Model Context Protocol.1MIT
- FlicenseNot gradedqualityCmaintenanceEnables querying aviation weather, FAA TFRs, NWS alerts, flight tracking, and Amtrak train status using public APIs. No API keys or private infrastructure required.-
- AlicenseAqualityBmaintenanceEnables authenticated access to a pilot's flight-planning account, letting an assistant search installed airfield charts offline, pull full airfield records with pilot notes and live feedback, and list, read, or download flightplans from local disk or cloud storage.102MIT