travel-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., "@travel-mcp-serverwhat's the cheapest flight from Lahore to London on 15 December?"
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.
travel-mcp-server
Ask your AI assistant real travel questions, like "What's the cheapest flight from Lahore to London on 15 December?", and get answers from live flight data, using your own API key.
🎬 Demo GIF coming soon. See docs/DEMO.md to record one.
travel-mcp-server is a Model Context Protocol server. It gives Claude Desktop, Claude Code, Cursor, Gemini CLI, ChatGPT and other MCP clients tools for:
✈️ Flight prices: one-way and round-trip fares from 700+ airlines and agents (via FlightAPI).
🛰️ Flight status: is EK623 on time? Which gate?
🛫 Airport boards: upcoming departures and arrivals at any airport.
🔎 Airport search: "Lahore" →
LHE, "Makkah" →JED. Works offline and needs no key.💱 Currency conversion: European Central Bank reference rates. Free, no key.
It is built to protect your API credits: it caches responses, enforces per-minute and per-day limits, and shows usage on request.
Contents
Related MCP server: Aviation MCP Server
Quick start (5 minutes)
1. Get a FlightAPI key (about 1 minute). Sign up at flightapi.io and copy your key from the dashboard. The free plan includes 100 requests per 30 days. A price search costs 2 credits.
No key yet? You can still install the server.
search_airportsandconvert_currencywork without one, and the flight tools explain how to add a key.
2. Add the server to your AI app (about 2 minutes). Pick your client below. You need Node.js 20+ for npx.
3. Ask. Restart your app and try:
What's the cheapest flight from Lahore to London on 15 December?
Claude Desktop
Open Settings → Developer → Edit Config. This opens claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\). Add:
{
"mcpServers": {
"travel": {
"command": "npx",
"args": ["-y", "mcp-server-travel"],
"env": {
"FLIGHTAPI_KEY": "your_flightapi_key"
}
}
}
}Fully quit and reopen Claude Desktop. The tools appear under the 🔧 / "Search and tools" menu.
Claude Code
claude mcp add --transport stdio --scope user --env FLIGHTAPI_KEY=your_flightapi_key travel -- npx -y mcp-server-travelCheck it with claude mcp list, or /mcp inside a session. Drop --scope user to add it to the current project only.
Cursor
Create or edit ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project):
{
"mcpServers": {
"travel": {
"command": "npx",
"args": ["-y", "mcp-server-travel"],
"env": {
"FLIGHTAPI_KEY": "your_flightapi_key"
}
}
}
}Then open Cursor Settings → MCP and make sure travel is enabled. Ask your question in Agent mode.
Gemini CLI
Add to ~/.gemini/settings.json (all projects) or .gemini/settings.json (one project):
{
"mcpServers": {
"travel": {
"command": "npx",
"args": ["-y", "mcp-server-travel"],
"env": {
"FLIGHTAPI_KEY": "$FLIGHTAPI_KEY"
}
}
}
}Gemini CLI expands $FLIGHTAPI_KEY from your shell environment, so the key stays out of the file. Run /mcp in Gemini CLI to check the server is connected.
ChatGPT (HTTP mode)
ChatGPT connects to remote MCP servers over HTTPS. That needs the Streamable HTTP transport and a public URL.
ChatGPT's connector settings offer OAuth or "No authentication", not a custom bearer header. So for ChatGPT, enable the secret-path token: the URL itself acts as the password.
# 1. Start the server in HTTP mode (keep this terminal open)
export FLIGHTAPI_KEY=your_flightapi_key
export MCP_HTTP_TOKEN=$(openssl rand -hex 32)
export MCP_HTTP_ALLOW_PATH_TOKEN=true
echo "Your token: $MCP_HTTP_TOKEN"
npx -y mcp-server-travel --http
# 2. In another terminal, give it a public HTTPS URL, e.g. with Cloudflare Tunnel:
cloudflared tunnel --url http://localhost:3000
# -> https://random-words.trycloudflare.comRestart step 1 with MCP_HTTP_ALLOWED_HOSTS=random-words.trycloudflare.com so the server accepts that hostname. This is DNS rebinding protection: requests with any other Host header get a 403.
Then, in ChatGPT, turn on Developer mode and create a connector (app) with:
MCP server URL:
https://random-words.trycloudflare.com/mcp/<your token>Authentication: No authentication. The secret path is the credential.
OpenAI moves these settings around from time to time. See OpenAI's Developer mode guide for the current menu location and which plans support it.
Any client that can send headers should use
Authorization: Bearer <token>againsthttps://your-host/mcpinstead. For a permanent setup, see Running remotely.
Example conversations
These show real questions and the shape of what the tools return to the model. The airport results are real output. Flight prices, times and exchange rates are illustrative: they show the exact output format, but live values depend on the day you ask.
"What's the cheapest flight from Lahore to London on 15 December?"
The model first resolves both cities (offline, no credits):
search_airports {"query": "Lahore"}
LHE/OPLA - Allama Iqbal International Airport, Lahore, Pakistan (large airport)
search_airports {"query": "London"}
LHR/EGLL - London Heathrow Airport, London, United Kingdom (large airport)
LGW/EGKK - London Gatwick Airport, London, United Kingdom (large airport)
LCY/EGLC - London City Airport, London, United Kingdom (medium airport)
...Then it searches prices (2 credits; cached for 30 minutes):
search_flight_prices {"origin": "LHE", "destination": "LHR", "departure_date": "2026-12-15", "currency": "GBP"}
One-way LHE -> LHR, 2026-12-15, 1 adult, economy
Showing 5 cheapest of 87 priced itineraries.
1. 412.30 GBP - Qatar Airways
Out: LHE 2026-12-15 04:10 -> LHR 2026-12-15 13:05 | 13h 55m | 1 stop via DOH | Qatar Airways [QR629, QR3]
Sold by: Qatar Airways, Mytrip
2. 455.80 GBP - Pakistan International Airlines
Out: LHE 2026-12-15 10:00 -> LHR 2026-12-15 14:40 | 9h 40m | non-stop | Pakistan International Airlines [PK757]
...
Note: prices are indicative, collected from airlines and travel agents by FlightAPI, and normally cover all passengers in the search. They change quickly and may exclude baggage or payment fees. Times are local to each airport. This tool cannot book; confirm and book on the airline or agent website.The assistant then answers in plain language, for example: "The cheapest option is about £412 with Qatar Airways via Doha (13h 55m). PIA's non-stop is about £456 and saves over 4 hours…"
"Is EK623 on time today?"
get_flight_status {"flight_number": "EK623", "date": "2026-10-17"}
Flight EK623 on 2026-10-17: In the air (1 hr 12 min remaining)
Departure: Dubai (DXB), terminal 3
scheduled 09:45, Oct 17, took off 10:02, Oct 17
Arrival: Allama Iqbal Intl (LHE)
scheduled 13:50, Oct 17, estimated 14:01, Oct 17
Times are local to each airport. Gates can change; check airport screens before travelling."What's leaving Doha in the next few hours?"
get_airport_schedule {"airport_code": "DOH", "type": "departures", "limit": 3}
Departures at Doha Hamad International Airport (DOH), times in Asia/Qatar
13:40 QR8221 to Frankfurt (FRA) - Qatar Airways - Scheduled
15:30 QR8860 to London (LHR) - Qatar Airways - Scheduled - gate C12
..."Umrah in February: what are my options from Karachi?"
Use the built-in umrah_flight_options prompt (in Claude Desktop: the ➕ / prompts menu). It resolves Karachi, searches both Jeddah (JED) and Madinah (MED) on a couple of dates, and compares them in a table. It keeps the number of searches small to save credits.
"How much is 450 GBP in US dollars?"
convert_currency {"amount": 450, "from": "GBP", "to": "USD"}
450 GBP = 607.93 USD (1 GBP = 1.350961 USD, ECB reference rate of 2026-10-16). Indicative only; card and bank rates differ."How many API calls have we used?"
get_usage {}
Usage since 2026-10-17T09:12:03.000Z (this server process):
FlightAPI key configured: yes
FlightAPI: 3 calls (~5 credits), 2 served from cache, 0 errors
Exchange rates: 1 call(s), 3 from cache
Safety limits: 9 of 10 left this minute, 97 of 100 left in the last 24h
Note: counters reset when the server restarts. Your FlightAPI dashboard shows your account-wide balance.Tools
Tool | What it does | Key inputs | Credits |
| Find airports by city, name, country or IATA/ICAO code. Understands aliases like Makkah, Madinah, Bombay. Main airports rank first. |
| 0 (offline) |
| Cheapest one-way or round-trip options: price, airlines, stops, duration, local departure/arrival times, sellers. |
| 2 per uncached search |
| Live status of one flight: scheduled/estimated/actual times, terminals, gates, baggage belt. |
| 1 per uncached call |
| Upcoming departures or arrivals: flight, airline, destination/origin, times, status, terminal, gate. |
| 2 per uncached call |
| Convert using ECB reference rates (about 30 major currencies). |
| 0 (free API) |
| Calls made, cache hits, estimated credits used, remaining safety limits. | none | 0 |
All inputs are validated with strict schemas before any API call:
IATA codes must be 3 letters and exist in the bundled airport list.
Dates must be real calendar dates, and not in the past.
Infants cannot outnumber adults, and seated passengers are capped at 9.
Unknown parameters are rejected.
Errors come back as short, friendly messages with a hint (for example [RATE_LIMITED] … Wait about 40 seconds…), never as stack traces.
Prompts
Prompt | Arguments | What it does |
|
| Searches airports, then prices, then summarizes the 3 best options (cheapest / fastest / best balance). |
|
| Compares flights to Jeddah (JED) and Madinah (MED) on two dates in the month, with a recommendation. |
Configuration
All settings are environment variables. See .env.example for a commented template. In desktop apps, put them in the server's "env" block.
Variable | Default | Description |
| none | Your FlightAPI key. Needed for prices, status and schedules. |
|
| Currency for prices when the user doesn't specify one. |
|
| Max FlightAPI requests per rolling minute ( |
|
| Max FlightAPI requests per rolling 24 h ( |
|
| Price search cache lifetime (minutes). |
|
| Flight status / airport board cache lifetime (minutes). |
|
| Exchange-rate cache lifetime (hours). |
|
| Persist the cache to |
| none | Custom cache file path (implies file cache). |
|
| Upstream timeout per attempt. |
|
|
|
|
| HTTP bind address ( |
|
| HTTP port ( |
| none | Required in HTTP mode. Bearer token, 16+ characters. |
|
| Also accept |
| none | Comma-separated public hostnames allowed in the |
|
|
|
CLI: npx -y mcp-server-travel [--http] [--port 3000] [--host 127.0.0.1] [--version] [--help]
How your credits are protected
FlightAPI charges per request, and AI models sometimes call tools more often than needed. The server stands between the model and your wallet:
Validation first. Malformed codes, past dates, impossible passenger mixes and unknown airports are rejected locally, so they never cost a credit.
Caching. Identical price searches are answered from cache for 30 minutes, flight status and airport boards for 2 minutes, and exchange rates for 12 hours. Requests are normalized (
lhe=LHE), so trivial differences still hit the cache. If two identical calls arrive at the same time, they share one upstream request. EnableENABLE_FILE_CACHE=trueto keep the cache across restarts.Limits. At most
FLIGHTAPI_MAX_PER_MINUTE(default 10) andFLIGHTAPI_MAX_PER_DAY(default 100) real FlightAPI calls. Cache hits are free and still served when a limit is reached. The model gets a clear message such as "Per-minute safety limit reached… Wait about 40 seconds" and can tell you.Conservative retries. Each request times out after 10 s. Network errors and timeouts are retried once with backoff. HTTP errors (4xx and 5xx) are never retried, because a retry could be billed again.
Bounded queries. Airport boards always request a single day. Without that, FlightAPI returns 10 days and charges accordingly.
Visibility.
get_usagereports calls per endpoint, cache hits and estimated credits (from FlightAPI's published costs). Your FlightAPI dashboard remains the source of truth for your balance.
Running remotely (HTTP mode, Docker, HTTPS)
HTTP mode serves stateless Streamable HTTP at POST /mcp. Cache, limits and usage are shared across all requests. There is also a GET /healthz health check.
FLIGHTAPI_KEY=... MCP_HTTP_TOKEN=$(openssl rand -hex 32) npx -y mcp-server-travel --http
# -> http://127.0.0.1:3000/mcp
curl -s http://127.0.0.1:3000/mcp \
-H "Authorization: Bearer $MCP_HTTP_TOKEN" \
-H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_airports","arguments":{"query":"Dubai"}}}'Clients that support remote servers with headers connect to https://your-host/mcp with Authorization: Bearer <token>. For example, Claude Code:
claude mcp add --transport http travel https://your-host/mcp --header "Authorization: Bearer YOUR_TOKEN"Docker
docker build -t travel-mcp-server .
docker run -d --name travel-mcp -p 127.0.0.1:3000:3000 \
-e FLIGHTAPI_KEY=your_flightapi_key \
-e MCP_HTTP_TOKEN=$(openssl rand -hex 32) \
-e MCP_HTTP_ALLOWED_HOSTS=travel.example.com \
travel-mcp-serverThe image runs as a non-root user, listens on 0.0.0.0:3000 inside the container, and includes a health check.
HTTPS (required for anything beyond localhost)
The server itself speaks plain HTTP and binds to 127.0.0.1 by default. Do not expose it directly to the internet. Put a TLS-terminating proxy in front:
Caddy (automatic certificates):
travel.example.com { reverse_proxy 127.0.0.1:3000 }nginx:
proxy_pass http://127.0.0.1:3000;inside aserver { listen 443 ssl; ... }block. Setproxy_buffering off;so streamed responses flush.Cloudflare Tunnel:
cloudflared tunnel --url http://localhost:3000(quick tests) or a named tunnel (permanent).
Then set MCP_HTTP_ALLOWED_HOSTS=travel.example.com. Use a long random token, keep FLIGHTAPI_MAX_PER_DAY set so a leaked token cannot drain your credits, and see SECURITY.md.
Troubleshooting
Symptom | Fix |
Tools don't appear in Claude Desktop | Fully quit the app (not just close the window) and reopen. Check the JSON is valid. Logs: macOS |
| The app can't find Node. Install Node 20+, or use the absolute path to |
|
|
| The key is wrong or inactive. Copy it again from the FlightAPI dashboard. |
| Your FlightAPI plan limit is used up (free plan: 100 requests / 30 days). Wait for the reset or upgrade. |
| This server's own safety limit. Wait, or raise |
"No priced itineraries were returned" | FlightAPI sometimes needs a second request to fill in results. Try again in a few minutes (empty results are cached for only 2 min), or try a nearby date. |
| Use |
| ECB publishes about 30 currencies. Ask |
HTTP mode: | Send |
HTTP mode: | Add your public hostname to |
Want to see what's happening | Set |
Data sources and licenses
Data | Source | License |
Flight prices, status, airport schedules | FlightAPI.io with your API key, under FlightAPI's terms | Commercial API |
Airports ( | Public domain | |
Airline names ( | OpenFlights airline database | |
Exchange rates | Frankfurter (European Central Bank reference rates) | Free, keyless API |
Regenerate the bundled datasets with npm run data:build (see scripts/build-datasets.ts). How the FlightAPI endpoints are used, and where the FlightAPI docs leave gaps, is documented in docs/FLIGHTAPI.md.
This project is not affiliated with FlightAPI, OurAirports, OpenFlights, Frankfurter or the ECB. Prices are indicative; always confirm with the airline or agent before booking.
Development
git clone https://github.com/lalchand07/travel-mcp-server.git && cd travel-mcp-server
npm install
npm test # 130+ tests, no network or API key needed
npm run dev # run from source (stdio)
npm run build && npm run inspect # MCP Inspector UIProject layout: src/tools/ (one file per tool), src/providers/ (FlightAPI, Frankfurter, airport and airline data), src/summarize/ (compact, model-friendly output), src/lib/ (cache, limiter, HTTP client, validation). See PLAN.md for the design and CONTRIBUTING.md for guidelines.
Roadmap
🏨 Hotels: search and price comparison through a hotel provider.
🛂 Visa requirements: entry rules by passport and destination.
🔌 More flight providers: pluggable providers (e.g. Amadeus, Duffel, Kiwi) so you can use the key you already have.
📅 Flexible dates: cheapest day in a month, with a strict credit budget.
🔐 OAuth for HTTP mode: first-class ChatGPT and remote client auth instead of the secret path.
🌍 More currencies: an optional provider for currencies the ECB doesn't publish (PKR, AED, SAR, ...).
Ideas and pull requests are welcome. Open an issue.
Built by
[Your Name], [Your Company]. [Contact / website link]
If this project saves you time, a ⭐ on GitHub helps others find it.
License
MIT. Bundled data has its own licenses; see Data sources and licenses.
Available Tools
6 toolsconvert_currencyConvert currencyARead-onlyIdempotent
Convert an amount between currencies using European Central Bank reference rates (published once per working day). Good for comparing fares quoted in different currencies. Free and keyless; rates are cached for 12 hours. Covers about 30 major currencies (USD, EUR, GBP, INR, TRY, CNY, JPY, ...); currencies the ECB does not publish (e.g. PKR, AED, SAR) are not available.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | Target currency, ISO 4217, e.g. USD. | |
| from | Yes | Source currency, ISO 4217, e.g. GBP. | |
| amount | Yes | Amount to convert, e.g. 450. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent) and open-world behavior. The description goes further by disclosing the data source, archival frequency (once per working day), 12-hour caching, keyless/free access, and coverage limits — operational facts annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four well-bounded sentences that front-load the core action, then layer source, use case, cost/latency, and coverage. Every sentence adds a fact an agent needs; slightly dense but no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple 3-param read-only tool with no output schema, the description covers what it does, data provenance, freshness, limits, and cost. The only mild gap is that it doesn't describe the response shape (converted amount, rate), though annotations render that low-stakes.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%; every parameter (amount, from, to) is fully documented with types, patterns, and examples. The description adds the currency-coverage caveat (unsupported codes like PKR, AED) which is genuinely useful beyond the schema, but does not clarify parameter syntax further. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource ('Convert an amount between currencies') with the data source named (ECB reference rates). It is clearly distinguishable from all siblings, none of which deal with currency, and the description preempts confusion by naming supported and unsupported currencies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context ('Good for comparing fares quoted in different currencies') and an explicit negative boundary (currencies the ECB does not publish are unavailable). It does not name an alternative tool for unsupported currencies, but the exclusion is concrete enough to route the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_airport_scheduleGet airport departures or arrivalsARead-onlyIdempotent
Upcoming departures or arrivals at an airport (flight number, airline, destination/origin, scheduled and estimated local times, status, terminal and gate). Use type "departures" or "arrivals". Uses the FlightAPI key (2 credits per uncached call); results are cached for 2 minutes.
| Name | Required | Description | Default |
|---|---|---|---|
| day | No | Which day (airport local time). Default today. | today |
| type | Yes | Which board to show. | |
| limit | No | Maximum flights to return (1-50, default 15). | |
| airport_code | Yes | Airport IATA code, e.g. DXB. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly/openWorld/idempotent already cover the safety profile), the description adds genuinely useful operational context: 2 credits per uncached call and a 2-minute cache window. That pricing and caching detail is exactly the kind of behavioral trait annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose and returned fields, then a short usage note, then cost/caching. Every sentence carries information with minimal waste, though the field enumeration in parentheses is fairly dense.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description helpfully lists returned fields; annotations cover the read-only safety profile; and cost plus cache lifetime complete the picture. The only missing piece is disambiguation from the single-flight sibling tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents airport_code, type, day, and limit. The description only echoes the type enum values, adding nothing beyond what the schema provides, which lands at the baseline for full coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific resource (upcoming departures/arrivals at an airport) and enumerates returned fields, so the agent knows exactly what data comes back. However, it never distinguishes this from the sibling get_flight_status, which an agent could plausibly confuse with a per-airport board versus a single-flight lookup.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Use type 'departures' or 'arrivals'" clarifies a parameter value, not when to choose this tool over siblings like get_flight_status or search_flight_prices. Usage context is implied by the resource name but no alternatives or exclusions are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_flight_statusGet flight statusARead-onlyIdempotent
Live status of a specific flight by flight number and date: scheduled/estimated/actual times, terminals, gates, baggage belt and whether it has departed or landed. Example: flight_number "EK623", date "2026-12-15". Uses the FlightAPI key (1 credit per uncached call); results are cached for 2 minutes.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Flight date (local departure date), YYYY-MM-DD, within 7 days of today. | |
| flight_number | Yes | Airline code + number, e.g. PK757, EK 623, BA107. | |
| departure_airport | No | Optional departure airport IATA code; only needed if the same flight number departs from several airports that day. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only, idempotent, open-world behavior, but the description adds cost and freshness context the annotations cannot convey: 'FlightAPI key (1 credit per uncached call)' and 'results are cached for 2 minutes'. That is exactly the kind of operational detail an agent should know before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences plus a concrete example, with the return payload front-loaded before the operational caveats. No filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description compensates by naming the returned fields, and it also covers cost and cache TTL. Input constraints (date window, IATA pattern) live in the schema, so nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents flight_number, date, and departure_airport formats and constraints. The description restates the two required inputs and supplies example values, but adds no semantics for departure_airport beyond what the schema already says. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Live status of a specific flight by flight number and date') and enumerates the response contents: scheduled/estimated/actual times, terminals, gates, baggage belt, departed/landed. This distinguishes it from get_airport_schedule (all flights at an airport) and search_flight_prices without requiring schema inspection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete invocation example and effectively scopes usage to a single flight identified by number+date, which separates it from the airport-wide sibling. It does not explicitly name alternatives like get_airport_schedule or state exclusions, so it falls just short of the when/when-not bar.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_usageGet API usageARead-only
Shows how many FlightAPI and exchange-rate calls this server has made since it started, how many were served from cache, estimated FlightAPI credits spent, and the remaining per-minute and per-day safety limits. Uses no credits.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint=true and openWorldHint=false, so the safety profile is partly covered. The description adds genuinely new behavioral context: the counters are cumulative 'since it started' (explaining the non-idempotent, changing return values) and the call is free ('Uses no credits'), which the annotations do not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core purpose, followed by a short cost note. The longer first sentence is a necessary field enumeration because no output schema exists, so nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly carries the burden of describing the return values and does so field by field, plus notes cost and limit semantics. Minor gaps remain (e.g., response format, whether counts are server-wide or per-key, when limits reset), but nothing essential for invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; the schema and description are consistent. Baseline 4 applies for a parameterless tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Shows) and resource (this server's API usage), then enumerates exactly what is reported: call counts, cache hits, credits spent, and remaining per-minute/per-day limits. This clearly separates it from the sibling tools, all of which fetch external travel/currency data rather than server telemetry.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied — an agent can infer this is for checking quota/credit consumption before or after making calls, and 'Uses no credits' hints it is safe to poll. However, the description names no trigger condition and no alternative, so the when-to-use is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_airportsSearch airportsARead-onlyIdempotent
Find airports by city, airport name, country, or IATA/ICAO code (e.g. "Lahore", "Heathrow", "JED", "OPLA"). Use this first to turn a city name into the 3-letter IATA codes required by search_flight_prices, get_flight_status and get_airport_schedule. Works offline from a bundled OurAirports dataset and uses no API credits. Larger airports are ranked first.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum results (1-20, default 8). | |
| query | Yes | City, airport name, country, or IATA/ICAO code. Examples: "London", "Madinah", "LHE". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnly, idempotent, closed-world), and the description adds non-obvious operational facts on top: it runs offline from a bundled OurAirports dataset, consumes no API credits, and ranks larger airports first. These materially affect how an agent budgets calls and interprets result ordering.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core capability and immediately followed by the routing guidance and the cost/ranking caveats. No sentence is filler; each adds distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only lookup with a fully documented two-parameter schema, the description covers purpose, workflow position, cost model, and ordering. The only mild gap is the exact shape of a returned record (fields available per airport), which no output schema supplies, but the intended use case does not strictly require it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3; the description goes slightly beyond by giving worked examples of query inputs and by explaining that results are size-ranked, which informs how the limit parameter should be set. It adds context rather than merely restating the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Find) plus resource (airports) and enumerates the searchable keys (city, airport name, country, IATA/ICAO code) with concrete examples. An agent can immediately distinguish it from siblings like search_flight_prices or get_airport_schedule, which consume codes rather than resolve them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'Use this first' and names the downstream tools (search_flight_prices, get_flight_status, get_airport_schedule) that require the IATA codes this tool produces. The when-to-use condition and the alternative-avoidance path are both spelled out, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_flight_pricesSearch flight pricesARead-onlyIdempotent
Search live flight prices between two airports for a date (one-way), or with return_date (round trip). Returns the cheapest options with airline, total price, stops, duration and local departure/arrival times. Airports must be 3-letter IATA codes: call search_airports first if you only know the city. Uses the FlightAPI key (2 credits per uncached search); identical searches are cached for 30 minutes. Prices are indicative; booking happens on the airline or travel agent website.
| Name | Required | Description | Default |
|---|---|---|---|
| adults | No | Adults (12+ years), 1-9. Default 1. | |
| origin | Yes | Departure airport IATA code, e.g. LHE. | |
| infants | No | Infants (under 2, on lap). Cannot exceed adults. Default 0. | |
| children | No | Children (2-11 years). Default 0. | |
| currency | No | ISO 4217 currency for prices, e.g. USD, GBP, PKR, EUR. Default USD. | |
| cabin_class | No | Cabin class. Default economy. | economy |
| destination | Yes | Arrival airport IATA code, e.g. LHR. | |
| max_results | No | How many of the cheapest options to return (1-20, default 5). | |
| return_date | No | Return date for a round trip, YYYY-MM-DD. Omit for one-way. | |
| departure_date | Yes | Outbound date, YYYY-MM-DD (today or later). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/openWorld/idempotent, and the description adds substantive behavior beyond them: cost accounting (2 credits per uncached search), 30-minute caching semantics, indicative (non-bookable) prices, and that fulfillment happens off-platform. This is exactly the extra context an agent needs to decide whether to spend credits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core operation and mode distinction, then layers output shape, constraints, cost, and disclaimer. Four sentences, each carrying distinct information with no repetition of the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description takes on the return-value burden and does so explicitly (airline, total price, stops, duration, local departure/arrival times). Combined with cost, cache, and booking caveats, an agent has everything needed to call and interpret this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents every parameter including defaults and formats. The description restates the IATA 3-letter constraint and return_date's one-way semantics, adding only marginal value over the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (search live flight prices) and immediately defines the two operating modes with their differentiator (one-way vs. return_date round trip). It also names the sibling search_airports as the prerequisite when only a city is known, so an agent can place it precisely among the five siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit usage context: one-way vs. round-trip driven by return_date, and a clear alternative/precondition for the IATA-code requirement (call search_airports first). The caching note (identical searches cached 30 min) further informs when re-calling is wasteful.
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.
6 tool updates
v0.1.0- First observed
convert_currency - First observed
get_airport_schedule - First observed
get_flight_status - First observed
get_usage - First observed
search_airports - First observed
search_flight_prices
TDQS
Scored across 6 tools
Each tool targets a distinct resource and action: airport lookup, price search, flight status, airport schedule, currency conversion, and usage stats. There is no meaningful overlap—search_airports (reference data) is clearly separated from search_flight_prices (live pricing) and get_flight_status (single flight) vs get_airport_schedule (airport-wide board).
All names follow a consistent snake_case verb_noun pattern (get_usage, search_airports, search_flight_prices, get_flight_status, get_airport_schedule, convert_currency). The verbs vary but each semantically matches its action, which is appropriate rather than inconsistent.
Six tools is well-scoped for a flight/currency lookup server—each one earns its place and there is no filler. Neither sparse nor bloated.
The surface covers the full read-only travel-info workflow: resolve codes, search prices, check live status, view schedules, convert currencies, and monitor limits. Booking is explicitly deferred to external sites, so the only minor gaps are niceties like multi-city or seat availability, which are arguably out of scope.
Maintenance
Related MCP Connectors
Search and compare flight offers through a cache-aware Streamable HTTP MCP server for AI agents.
Flight search MCP server providing search, pagination, and itinerary details for AI assistants.
AI marketplace — flights, tours, activities, transport & more via MCP. No auth required.
Pay-per-use tool marketplace for AI agents. Search, price-check, and call APIs via MCP.
Related MCP Servers
- AlicenseAqualityAmaintenanceProvides real-time foreign-exchange rates, historical data, and multi-currency lookups to MCP-compatible AI coding assistants like Claude Code and Cursor.4515 npmMIT
- AlicenseAqualityCmaintenanceMCP server giving AI agents access to real-time aviation data — live flight tracking, airport weather, airline and airport information.1016 PyPI3MIT
- AlicenseBqualityDmaintenanceEnables AI assistants to query flight routes, real-time flight tracking, weather, and transfer flights via standardized MCP tools.10MIT
- AlicenseNot gradedqualityDmaintenanceProvides live flight prices, booking links, and airport lookup via a hosted MCP server. Enables search for flights and direct booking URL retrieval.1MIT