Skip to main content
Glama
lichen911

Aviation MCP Server

by lichen911

Aviation MCP Server

A FastMCP server that provides real-time aircraft data from ADS-B Exchange (adsb.lol API) via Streamable HTTP transport.

Features

  • šŸš€ Streamable HTTP Transport - Modern HTTP with JSON-RPC protocol

  • šŸ” API Key Authentication - Secure access control

  • ⚔ FastMCP Framework - High-performance MCP server

  • šŸ›« Real-time Aircraft Data - Live ADS-B data from adsb.lol

  • šŸ“” Multiple Query Types - 8 different ways to query aircraft data

  • 🐳 Production Ready - Can run standalone or in containers

Related MCP server: adsb-mcp-server

Quick Start

Installation

cd aviation-mcp-server
uv sync

Running the Server

Development:

uv run aviation-mcp-server-http

With Custom Configuration:

export MCP_HOST="0.0.0.0"
export MCP_PORT="8000"
export MCP_API_KEY="your-secret-key"
uv run aviation-mcp-server-http

The server will start on http://0.0.0.0:8000/mcp

Configuration

Environment variables:

MCP_HOST=0.0.0.0                          # Server bind address (default: 0.0.0.0)
MCP_PORT=8000                             # Server port (default: 8000)
MCP_API_KEY=your-secret-key               # API key for authentication (default: dev key)

API Documentation

Endpoint

  • URL: http://localhost:8000/mcp

  • Method: POST

  • Content-Type: application/json

  • Accept: application/json, text/event-stream

Authentication

Include API key in one of these headers:

  • X-API-Key: your-secret-key

  • Authorization: Bearer your-secret-key

Available Tool: query_aircraft

Query real-time aircraft data from ADS-B Exchange.

Parameters

  • query_type (required): Type of query

    • "callsign": Search by flight callsign (e.g., "UAL123")

    • "registration": Search by aircraft registration (e.g., "N12345")

    • "aircraft_type": Search by aircraft type (e.g., "B738", "A320")

    • "icao_hex": Search by ICAO hex code

    • "squawk": Search by transponder squawk code (e.g., "7700")

    • "location": Search within radius of coordinates

    • "military": Get all military aircraft

    • "privacy": Get aircraft with privacy ICAO addresses

  • value (optional): Search value for most query types

  • latitude (optional): Latitude for location queries (-90 to 90)

  • longitude (optional): Longitude for location queries (-180 to 180)

  • radius (optional): Search radius in nautical miles for location queries

Example Requests

List Available Tools:

curl -X POST http://localhost:8000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "X-API-Key: adsb-mcp-secret-key-change-in-production" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list",
    "params": {}
  }'

Query Military Aircraft:

curl -X POST http://localhost:8000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "X-API-Key: adsb-mcp-secret-key-change-in-production" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "query_aircraft",
      "arguments": {
        "query_type": "military"
      }
    }
  }'

Query by Callsign:

curl -X POST http://localhost:8000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "X-API-Key: adsb-mcp-secret-key-change-in-production" \
  -d '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "query_aircraft",
      "arguments": {
        "query_type": "callsign",
        "value": "UAL123"
      }
    }
  }'

Query by Location:

curl -X POST http://localhost:8000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "X-API-Key: adsb-mcp-secret-key-change-in-production" \
  -d '{
    "jsonrpc": "2.0",
    "id": 4,
    "method": "tools/call",
    "params": {
      "name": "query_aircraft",
      "arguments": {
        "query_type": "location",
        "latitude": 40.7128,
        "longitude": -74.0060,
        "radius": 50
      }
    }
  }'

Testing

Test Server Connectivity

uv run python test_server.py

This will:

  1. Test military aircraft query

  2. Test callsign query

  3. Verify API connectivity

Manual Health Check

curl -I http://localhost:8000/mcp

Expected: 405 Method Not Allowed (GET not supported, use POST)

Integration

Discord Bot

The aviation-discord-bot project can connect to this server:

MCP_TRANSPORT=http
MCP_SERVER_URL=http://localhost:8000/mcp
MCP_API_KEY=your-secret-key

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "adsb-aircraft-data": {
      "command": "bash",
      "args": ["-c", "cd /path/to/aviation-mcp-server && uv run aviation-mcp-server-http"],
      "env": {
        "MCP_API_KEY": "your-secret-key"
      }
    }
  }
}

Other MCP Clients

Any MCP client supporting HTTP transport can connect using:

  • Transport: HTTP

  • URL: http://localhost:8000/mcp

  • Protocol: JSON-RPC 2.0

  • Authentication: API key via X-API-Key header

Architecture

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  MCP Client    │
│  (Bot/Claude)  │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
         │
         │ HTTP POST + JSON-RPC
         │ + X-API-Key header
         │
         ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  FastMCP       │
│  + uvicorn     │
│  + Auth        │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
         │
         │ HTTPS
         │
         ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  adsb.lol API  │
│  (ADS-B Data)  │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Deployment

Docker

FROM python:3.12-slim
WORKDIR /app
COPY . .
RUN pip install uv && uv sync
ENV MCP_API_KEY=${MCP_API_KEY}
ENV MCP_HOST=0.0.0.0
ENV MCP_PORT=8000
EXPOSE 8000
CMD ["uv", "run", "aviation-mcp-server-http"]

Build and run:

docker build -t aviation-mcp-server .
docker run -p 8000:8000 -e MCP_API_KEY=your-secret-key aviation-mcp-server

Kubernetes

apiVersion: apps/v1
kind: Deployment
metadata:
  name: aviation-mcp-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: aviation-mcp-server
  template:
    metadata:
      labels:
        app: aviation-mcp-server
    spec:
      containers:
      - name: server
        image: aviation-mcp-server:latest
        ports:
        - containerPort: 8000
        env:
        - name: MCP_API_KEY
          valueFrom:
            secretKeyRef:
              name: mcp-secrets
              key: api-key
---
apiVersion: v1
kind: Service
metadata:
  name: aviation-mcp-server
spec:
  selector:
    app: aviation-mcp-server
  ports:
  - port: 80
    targetPort: 8000
  type: LoadBalancer

systemd Service

Create /etc/systemd/system/aviation-mcp-server.service:

[Unit]
Description=Aviation MCP Server
After=network.target

[Service]
Type=simple
User=adsb
WorkingDirectory=/opt/aviation-mcp-server
Environment="MCP_API_KEY=your-secret-key"
Environment="MCP_HOST=0.0.0.0"
Environment="MCP_PORT=8000"
ExecStart=/usr/local/bin/uv run aviation-mcp-server-http
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl enable aviation-mcp-server
sudo systemctl start aviation-mcp-server
sudo systemctl status aviation-mcp-server

Security

Production Recommendations

  1. Use HTTPS: Deploy behind reverse proxy (nginx, Caddy) with TLS

  2. Secure API Keys: Use secrets management (AWS Secrets Manager, HashiCorp Vault)

  3. Rate Limiting: Implement rate limiting to prevent abuse

  4. Monitoring: Add logging and metrics (Prometheus, Grafana)

  5. IP Filtering: Restrict access to known client IPs

  6. Regular Updates: Keep dependencies updated

Example nginx Configuration

upstream adsb_mcp {
    server 127.0.0.1:8000;
}

server {
    listen 443 ssl http2;
    server_name mcp.example.com;

    ssl_certificate /etc/ssl/certs/mcp.crt;
    ssl_certificate_key /etc/ssl/private/mcp.key;

    location /mcp {
        proxy_pass http://adsb_mcp;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Rate limiting
        limit_req zone=mcp_limit burst=10 nodelay;
    }
}

Troubleshooting

Server won't start

  • Check if port 8000 is already in use: lsof -i :8000

  • Verify dependencies: uv sync

  • Check Python version: python --version (requires 3.10+)

Authentication errors

  • Verify API key in request headers

  • Check server logs for authentication failures

  • Ensure API key matches MCP_API_KEY environment variable

API errors

  • Verify internet connectivity to adsb.lol

  • Check adsb.lol API status

  • Review server logs for error details

Performance issues

  • Monitor server resources (CPU, memory)

  • Check network latency to adsb.lol API

  • Consider implementing caching

Development

Project Structure

aviation-mcp-server/
ā”œā”€ā”€ src/
│   └── aviation_mcp_server/
│       ā”œā”€ā”€ __init__.py
│       └── server.py          # Main server implementation
ā”œā”€ā”€ pyproject.toml             # Dependencies
ā”œā”€ā”€ .python-version            # Python version (3.12)
ā”œā”€ā”€ README.md                  # This file
└── test_server.py             # Connectivity tests

Adding New Tools

To add a new MCP tool, edit server.py:

@mcp.tool()
async def your_new_tool(param1: str, param2: int) -> str:
    """
    Description of your tool.

    Args:
        param1: Description
        param2: Description

    Returns:
        Result description
    """
    # Implementation
    return "result"

Running Tests

# Test server connectivity
uv run python test_server.py

# Manual API test
curl -X POST http://localhost:8000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "X-API-Key: adsb-mcp-secret-key-change-in-production" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

API Data Source

This server uses the adsb.lol API, which provides:

  • Real-time aircraft positions

  • Flight information (callsign, altitude, speed)

  • Aircraft details (type, registration)

  • Military aircraft tracking

  • Worldwide coverage

License

MIT

Contributing

Contributions welcome! Please:

  1. Fork the repository

  2. Create a feature branch

  3. Make your changes

  4. Add tests if applicable

  5. Submit a pull request

Support

For issues or questions:

  • Check the troubleshooting section

  • Review server logs

  • Test with manual curl requests

  • Verify environment variables

Acknowledgments


Version: 0.1.0 Status: Production Ready Last Updated: 2025-10-12

Available Tools

2 tools
query_aircraftA

Query real-time aircraft data from ADS-B Exchange.

You can search for aircraft by various criteria including callsign, registration, aircraft type, location, squawk code, ICAO hex, or get special categories like military aircraft or aircraft with privacy addresses.

ParametersJSON Schema
NameRequiredDescriptionDefault
valueNoThe search value (callsign, registration, type code, etc.). Not required for 'military' or 'privacy' queries.
radiusNoSearch radius in nautical miles for location queries
latitudeNoLatitude for location-based queries (-90 to 90)
longitudeNoLongitude for location-based queries (-180 to 180)
query_typeYesType of query to perform. Options: - "callsign": Search by flight callsign (e.g., 'UAL123') - "registration": Search by aircraft registration (e.g., 'N12345') - "aircraft_type": Search by aircraft type (e.g., 'B738', 'A320') - "icao_hex": Search by ICAO hex code (e.g., 'A12B34') - "squawk": Search by transponder squawk code (e.g., '7700') - "location": Search within radius of coordinates - "military": Get all military aircraft - "privacy": Get all aircraft with privacy ICAO addresses

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It mentions 'real-time' data, implying a read operation, but does not disclose rate limits, data freshness, authentication needs, or any limitations. Minimal behavioral transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences long. The first sentence states the core purpose, and the second lists search criteria. Every sentence earns its place without redundancy. Front-loaded and efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 5 parameters and an output schema exists, the description covers the query types and parameter usage well. It lacks usage caveats (e.g., rate limits, error handling) but output schema likely documents return structure. Overall complete for typical use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, baseline 3. The description adds significant value by explaining the meaning of each query_type and the conditions for 'value', 'radius', 'latitude', and 'longitude' parameters. It clarifies which parameters are needed for different query types, exceeding the schema's descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Query real-time aircraft data from ADS-B Exchange.' It lists specific search criteria, distinguishing it from the sibling 'query_registration' which likely focuses on registration lookups. The verb 'Query' and resource 'aircraft data' are specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use each query_type (e.g., 'callsign', 'military'), providing explicit context. However, it does not include when-not-to-use or compare directly with the sibling tool 'query_registration', which would improve guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_registrationA

Query FAA aircraft registration database.

Search the FAA aircraft registration database for detailed information about registered aircraft, including owner information, aircraft specifications, and registration status.

ParametersJSON Schema
NameRequiredDescriptionDefault
valueYesThe search value (N-Number, serial number, or Mode S code)
query_typeYesType of query to perform. Options: - "n_number": Search by N-Number/registration (e.g., '100', '1000A', 'N12345') - "serial": Search by aircraft serial number - "mode_s": Search by Mode S code hex (e.g., 'A004B3')

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden for behavioral disclosure. It does not mention that this is a read-only operation, any rate limits, authentication requirements, or potential side effects. The agent is left without important safety context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description consists of two concise, front-loaded sentences. The first sentence states the core action, and the second expands on what information is returned. No superfluous text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema, the description adequately covers the tool's purpose and parameters. However, it omits potential limitations (e.g., result count limits, pagination) which would be helpful for a query tool. It is minimally complete but not thorough.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the description's parameter field provides concrete examples for 'value' (e.g., 'N12345', 'A004B3') and enumerates possible 'query_type' options with examples. This adds meaningful context beyond the schema's property descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly specifies the tool's action ('Query') and resource ('FAA aircraft registration database'), and details the kind of information returned (owner info, specs, status). Despite not contrasting with sibling tool 'query_aircraft', the purpose is unambiguous and specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

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 (e.g., 'query_aircraft'), nor does it mention prerequisites or exclusions. The agent lacks context to differentiate use cases.

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.

  1. 2 tool updatesv0.1.0
    • First observedquery_aircraft
    • First observedquery_registration

TDQS

A3.9/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have clearly distinct purposes: one queries real-time aircraft data from ADS-B Exchange, the other queries the FAA registration database. There is no overlap in functionality.

Naming Consistency5/5

Both tools follow a consistent verb_noun pattern ('query_aircraft', 'query_registration'), making them predictable and easy to understand.

Tool Count4/5

With only two tools, the server is minimal but covers two primary aviation data sources. It feels slightly thin but is reasonable for a focused purpose.

Completeness4/5

The server covers real-time tracking and registration lookup, which are core aviation queries. Minor gaps exist (e.g., historical data, airport info), but the main workflows are supported.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers