Skip to main content
Glama
PythonicMind2

flight-search-mcp

README.md
<div align="center">

# ✈️ flight-search-mcp

**A Model Context Protocol server for live flight tracking — built with the official MCP Python SDK, powered by a genuinely free API.**

[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](pyproject.toml)
[![MCP](https://img.shields.io/badge/MCP-FastMCP-6E56CF.svg)](https://modelcontextprotocol.io)

Give Claude (or any MCP client) the ability to look up live flights, check real-time status, and resolve airport/airline codes — no paid API, no credit card.

</div>

---

## What this does

Ask your MCP client things like:

> *"Is flight BA100 delayed?"*
> *"What flights are currently in the air from JFK to LHR?"*
> *"What's the IATA code for Heathrow?"*

...and it answers with real, live data pulled straight from [AviationStack](https://aviationstack.com).

## Why AviationStack

AviationStack is the one that's still genuinely free for indie developers: **~100
requests/month, no credit card, API key in seconds.**

The trade-off: the free plan covers **current & near-term live flights only**
— no future-dated trip search, no historical data, no fares. This is a
flight *tracker*, not a trip planner. If you outgrow that, see
[Scope & limitations](#-scope--limitations) below.

## ✨ Features

- 🔍 **`search_flights`** — live flights by route, airline, or status
- 📡 **`get_flight_status`** — real-time status, gate, delay, live position for one flight
- 🛫 **`resolve_airport`** — city/airport name → IATA code
- 🏢 **`resolve_airline`** — airline name → IATA code
- ⚡ Smart caching — protects your monthly quota automatically
- 🛡️ Input validation with actionable error messages, not raw API errors
- ✅ Tested, typed, and small enough to actually read

## 🚀 Quickstart

```bash
git clone https://github.com/PythonicMind2/flight-search-mcp.git
cd flight-search-mcp
pip install -e .

cp .env.example .env
# paste your free AviationStack key into .env — get one at
# https://aviationstack.com/signup/free (instant, no card)

python -m flight_search_mcp.server
```

### Connect to Claude Desktop

Add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "flight-search": {
      "command": "python",
      "args": ["-m", "flight_search_mcp.server"],
      "cwd": "/absolute/path/to/flight-search-mcp",
      "env": {
        "AVIATIONSTACK_API_KEY": "your_api_key"
      }
    }
  }
}
```

Restart Claude Desktop and ask it about a flight.

## 🧰 Tools

| Tool | Args | Returns |
|---|---|---|
| `search_flights` | `origin?`, `destination?`, `airline_name?`, `flight_status?`, `max_results?` | Live flights matching at least one filter |
| `get_flight_status` | `flight_iata` (e.g. `"BA100"`) | Status, gate, delay, live position |
| `resolve_airport` | `keyword` (city or airport name) | Matching IATA codes |
| `resolve_airline` | `keyword` (airline name) | Matching IATA codes |

`search_flights` requires at least one of `origin`, `destination`, or
`airline_name` — an unfiltered call would burn quota on an arbitrary global
sample.

## 🏗️ Project structure

```
flight-search-mcp/
├── src/flight_search_mcp/
│   ├── server.py               # FastMCP server + tool definitions
│   ├── aviationstack_client.py # Async API client, caching, error handling
│   ├── models.py                # Pydantic response models
│   ├── cache.py                 # Minimal in-memory TTL cache
│   └── config.py                # Env-based settings
├── tests/test_server.py         # Parsing + validation tests (no network)
├── .github/workflows/tests.yml  # CI
├── .env.example
└── pyproject.toml
```

**Design choices worth knowing about:**
- **Auth** is a plain `access_key` query param — no OAuth token juggling.
- **Caching** is tiered: reference data (airports/airlines) is cached for an
  hour since it barely changes; live flight data for 30 seconds, mainly to
  absorb accidental duplicate calls in the same turn. Every cache hit is a
  request you don't spend against your ~100/month quota.
- **Errors**: AviationStack often returns HTTP `200` with an `"error"`
  object in the body instead of a 4xx. The client catches this and raises a
  real exception with a useful hint (quota exhausted, wrong key, paid-only
  feature) instead of silently returning nothing.

## 🧪 Testing

```bash
pip install pytest pytest-asyncio
pytest tests/ -v
```

All tests run against sample payloads — no API key or network access needed.

## ⚠️ Scope & limitations

AviationStack's free plan does **not** include:
- Future-dated trip search (`/flightsFuture` is paid-only)
- Historical flights beyond the current window
- `/routes` (date-independent schedule lookups — paid-only)
- Any pricing/fare data (AviationStack doesn't do fares on any plan)
- The `search` autocomplete param on `/airports`/`/airlines` (this repo
  works around it by filtering one reference page client-side)

If you need real future-dated search with prices, look at
[FlightAPI.io](https://www.flightapi.io) (small free trial, then paid) or
[Duffel](https://duffel.com) (free sandbox data forever, real data is
pay-per-use). PRs adding either as an optional second backend are welcome.

## 🤝 Contributing

Issues and PRs welcome. Keep it small, keep it tested.
---

<div align="center">
Built with the <a href="https://github.com/modelcontextprotocol/python-sdk">official MCP Python SDK</a>.
</div>

TDQS

A4.4/5.0

Scored across 4 tools

Disambiguation5/5

Each tool has a distinct purpose: get_flight_status for a specific flight, search_flights for multi-flight search, resolve_airport for IATA code lookup by city/airport name, and resolve_airline for airline code lookup. No overlap or ambiguity.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern: get_flight_status, search_flights, resolve_airport, resolve_airline. No mixing of styles or conventions.

Tool Count5/5

With 4 tools, the server is well-scoped for a flight search MCP: two lookups (airport/airline codes) and two flight operations (search and specific status). Each tool earns its place without being too few or too many.

Completeness5/5

The tool surface covers the core domain: resolving identifiers, searching live flights, and retrieving detailed status. Gaps like historical or future scheduled flights are explicitly out of scope, so no missing functionality for its stated real-time purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues