@cyanheads/faa-aircraft-registry-mcp-server
Click on "Install 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 entire US civil aircraft registry as an offline lookup server. Resolve a tail number to its aircraft, make/model, engine, year, and registered owner; search by owner, type, or state; decode manufacturer and engine codes to specs; and resolve registration status across active, deregistered, and reserved records.
The data is the FAA's Releasable Aircraft Database — the full registry published by the FAA Civil Aviation Registry as a public-domain bulk download (a US Government work, no copyright). There is no keyless live FAA registry API, so the server builds a local index from that download instead: MASTER → ACFTREF → ENGINE are pre-joined into an embedded SQLite + FTS5 index, and every coded field is decoded at query time. Queries hit that local index — keyless, no runtime network, no per-request rate limit.
The index is not bundled with the package. On first use the operator runs mirror:init to download and build it (see First-run setup). Owner name and address are redacted by default (see Owner-PII redaction).
Composes with live flight-tracking data: the Mode S (hex) code this server returns is the ICAO 24-bit address that OpenSky and similar feeds key on, so a tail number or transponder code seen in the air decodes here to its aircraft and status.
Related MCP server: NPI MCP Server
Tools
Five tools covering the registry — two exact-key lookups, two full-text searches, and one cross-file status resolver. Searches return decoded summaries with N-numbers (or 6–7-character reference codes) to drill into via the matching lookup.
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, 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. |
faa_lookup_registration
The primary tool. Decode one N-number to its full record in a single call.
Accepts
N12345or12345— the leadingNis optional, and the number is normalized before lookupResolves the
MASTER→ACFTREF→ENGINEjoin and decodes every coded field (aircraft type, engine type, status, airworthiness class, region) — each surfaced as both the raw FAA code and the decoded labelReturns the Mode S code in both octal and hex; the hex form is the ICAO 24-bit address used by live flight-tracking feeds
Owner name/address are included only when
FAA_REDACT_OWNER_PII=false; otherwiseownerRedacted: trueflags that they were withheldA known-but-inactive number (deregistered or reserved) is not found here — use
faa_get_registration_statusfor the cross-file answer
faa_get_registration_status
Resolve where an N-number stands across the registry, even when it is no longer active.
Checks the active (
MASTER), deregistered (DEREG), and reserved (RESERVED) files in priority order, returning a discriminatedrecordType:active,deregistered,reserved, orunknownA number that was never issued resolves to
recordType: "unknown"— a valid, informative answer rather than an errorEach branch carries the fields relevant to that state (active: status + airworthiness + dates; deregistered: cancel date + serial; reserved: reservation type + reserve/purge dates)
Owner-PII–free — returns status facts only
faa_search_registrations
Full-text search over active registrations, returning decoded summaries with N-numbers for follow-up.
Filter by
ownerName,makeModel,state,aircraftType, ormodeSCode; at least one filter is requiredOwner-name search is disabled when
FAA_REDACT_OWNER_PIIis on — search by make/model, state, type, or Mode S code insteadFree-text terms are column-scoped:
makeModelmatches make/model only, never owner name or cityEach result carries an N-number to pass to
faa_lookup_registrationfor full detailEvery response reports
totalCountacross all matches, so a partial result set is never mistaken for complete; page through it withlimit(1–200, default 25) andoffset— a truncated response names thenextOffsetto request
faa_search_aircraft_types
Discover the 6–7-character manufacturer/model/series codes by name before decoding them.
Filter by
query(manufacturer/model name, full-text),aircraftTypecode, orcategorycode; at least one filter is requiredReturns reference summaries with the code to pass to
faa_get_aircraft_typeEvery response reports
totalCountacross all matches; page through it withlimit(1–200, default 25) andoffset— a truncated response names thenextOffsetto request
Resources
Type | Name | Description |
Resource |
| Full registration record for one N-number — the same decoded, pre-joined payload as |
All registry data is also reachable via tools — the resource is a convenience for clients that inject resources as context. Tool-only clients (the majority) reach the same record through faa_lookup_registration, so no data is locked behind the resource. Search collections are not exposed as resources; use the search tools instead.
Features
Built on @cyanheads/mcp-ts-core:
Declarative tool and resource definitions — single file per primitive, framework handles registration and validation
Unified error handling — handlers throw, framework catches, classifies, and formats, with typed per-tool error contracts and recovery hints
Pluggable auth:
none,jwt,oauthSwappable storage backends:
in-memory,filesystem,Supabase,Cloudflare KV/R2/D1Structured logging with optional OpenTelemetry tracing
STDIO and Streamable HTTP transports
FAA-registry-specific:
Offline and keyless at runtime — every query hits the local SQLite + FTS5 index; no API key, no runtime network, no rate limit
Built on the framework
MirrorService:mirror:initbuilds the index out-of-band, and the HTTP server schedules a daily refresh aligned to the FAA's nightly re-releasePre-joined
MASTER→ACFTREF→ENGINErecords, so one call returns "2008 Cessna 172S, Lycoming IO-360, valid registration" rather than raw join codesFail-safe owner-PII redaction — redaction defaults on and drops owner name/address from output and disables owner-name search
Agent-friendly output:
Coded fields surface both the raw FAA code and the decoded label — the label for reasoning, the code so nothing is lost
Truncation disclosure — search tools flag
truncatedwithshown/capwhen the result set is capped, so a partial page is never read as the wholePermissible-field honesty — fields the FAA leaves blank (year, cruise speed, co-owner names) stay absent rather than fabricated
ownerRedactedflag on every affected payload, so the agent knows owner data was withheld and whyDiscriminated status output (
recordType) so callers branch on data, not string parsing
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.
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.
After installing, build the index out-of-band (never on server startup — a full parse of ~1M rows must not block start):
# Build the local index from the live FAA download (idempotent, resumable)
FAA_MIRROR_PATH=/path/to/faa-registry.db bun run mirror:init
# Verify it built (readiness + integrity check)
FAA_MIRROR_PATH=/path/to/faa-registry.db bun run mirror:verify
# Rebuild from the latest FAA release (run on a schedule, or out-of-band for stdio)
FAA_MIRROR_PATH=/path/to/faa-registry.db bun run mirror:refreshKeep 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); the index stays queryable throughout. 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.3 or higher (or Node.js v24+).
bun:sqliteis built into Bun; a Node-only deployment addsbetter-sqlite3(already declared as an optional peer dependency).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 installBuild the index (see First-run setup):
bun run mirror:initConfiguration
Variable | Description | Default |
| Redact owner name/address from output and disable owner-name search. Fail-safe: unset, empty, or malformed resolves to redacted. Set |
|
| Filesystem path to the SQLite index file. Point at a persistent path; mount a volume here in production. |
|
| Source URL for the FAA Releasable Aircraft Database ZIP, used by | FAA registry ZIP |
| Transport: |
|
| 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). |
|
| Enable OpenTelemetry instrumentation (spans, metrics, completion logs). |
|
See .env.example for the full list of optional overrides.
Owner-PII redaction
The FAA registry is releasable public record, but MASTER, DEREG, and RESERVED carry registrant names and physical addresses (deregistered records carry both mailing and physical address blocks plus co-owner names). This server ships a first-class redaction mode, redacted by default:
FAA_REDACT_OWNER_PIIdefaults totrue. Unset, empty, or malformed all resolve to redacted, so a deployment can never leak PII by omission or misconfiguration.When redacted: registrant name, street/physical address, and co-owner names are dropped from every output, and owner-name search is disabled (
faa_search_registrationsrejectsownerName). Disabling search matters — output-hiding alone would let an agent confirm a person↔aircraft link by probing the search input.Aircraft facts (make/model/engine/year/specs) and registration status still flow, with
ownerRedacted: trueon every affected payload.Full owner detail requires explicitly setting
FAA_REDACT_OWNER_PII=false— appropriate for a trusted local or self-hosted install, not a shared endpoint.
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 test suite 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 — |
| 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.tsThe registry index is the source of truth at runtime — there is no upstream API to retry; build and refresh it out-of-band, and never fabricate a value from a blank upstream field
Contributing
Issues and pull requests 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 installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceProvides 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.Last updated1MIT
- -license-quality-maintenanceEnables interaction with the CMS NPPES NPI Registry to search, lookup, and validate National Provider Identifier records. It features offline-capable search using a local SQLite database that automatically updates with the latest provider data.Last updated
- Alicense-qualityDmaintenanceProvides AI assistants with real-time aircraft tracking, FAA registration, and OpenSky flight data through the Model Context Protocol.Last updated1MIT
- AlicenseAqualityCmaintenanceExposes real-time ADS-B aircraft data from a feeder, enabling natural language queries for aircraft positions, receiver statistics, and flight searches.Last updated69GPL 3.0
Related MCP Connectors
Offline global aviation reference — airports, runways, navaids, frequencies from OurAirports.
Aircraft registry search, flight history, and analytics powered by ADS-B Exchange data.
Offline US medical code lookup and crosswalk — ICD-10-CM/PCS, HCPCS Level II, RxNorm. Keyless.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/cyanheads/faa-aircraft-registry-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server