aviation-mcp
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., "@aviation-mcpassess conditions at KLAX"
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.
aviation-mcp
An MCP tool server that exposes live aviation weather to an LLM — and, more to the point, knows when it shouldn't be trusted to answer.
Built in TypeScript against aviationweather.gov. No API key, no mock data.
aviation-mcp — eval suite
15 golden cases, frozen fixtures, no network
PASS VFR auto conf 1.00 clear VFR
PASS IFR auto conf 1.00 solid IFR — low ceiling
PASS VFR gated conf 0.75 thunderstorm with technically-VFR numbers
PASS IFR gated conf 0.65 sources disagree
...
── scores ──
category accuracy 100% (15/15)
gate precision 100% (5 correct escalations, 0 spurious)
gate recall 100% (0 missed escalations)
confidence separation gated 0.68 vs ungated 1.00The idea
Most tool servers are a thin wrapper over an API: the model asks, the tool answers, everyone assumes the answer is good. That's fine until the tool is asked something the underlying data can't actually support — at which point a language model will cheerfully produce a confident answer anyway, because that is what language models do.
So the interesting tool here isn't get_metar. It's assess_conditions, which returns three things instead of one:
{
"flightCategory": "VFR",
"confidence": 0.75,
"requiresHumanReview": true, // ← the point
"reviewReasons": [
"thunderstorm reported — category alone understates the hazard."
],
"reasoning": [
"No broken or overcast layer reported; ceiling is not a limiting factor.",
"Visibility 10 sm.",
"Category is the worse of the two components: VFR."
]
}Ceiling and visibility both say VFR. There is a thunderstorm overhead. The number is right and the answer is dangerous — so the tool refuses to present it as settled and hands off to a person.
Related MCP server: stormscope
The escalation gates
requiresHumanReview fires on four conditions, each of which is a way for a technically-correct answer to be wrong:
Gate | Why |
Boundary conditions | Visibility of exactly 3.0 sm sits on the IFR/MVFR line. The honest answer to "which side?" is "I can't tell you from this data." |
Missing inputs | Upstream omitted visibility. A naive implementation defaults to VFR and reports it confidently. Absence of data is not evidence of good weather. |
Significant weather | Thunderstorms, freezing rain, hail. The category is right; the category is also not the whole story. |
Source disagreement | Our computed category differs from upstream's own. One of us is wrong, and we don't get to assume it's them. |
Confidence degrades per gate and the eval suite asserts that gated cases actually score lower than ungated ones — otherwise the number is decorative.
What the eval harness caught
This is the part worth reading.
The first version used fixed boundary margins (±0.5 sm, ±200 ft). Every unit test passed. The implementation was, by any reasonable reading, correct.
The eval suite failed it at 56% gate precision. It was escalating half-mile fog as "near the 1 sm boundary" — half-mile fog is unambiguously the worst category there is — and a 700 ft overcast as "near 500 ft", when 700 ft is squarely IFR. It was crying wolf on a third of the cases, and a gate that fires on obvious cases is a gate humans learn to ignore.
The bug: fixed margins assume measurement precision is constant across magnitudes. It isn't. The gap between 0.5 and 1.0 sm is enormous; the gap between 700 and 500 ft is not. Switching to a proportional margin (5% of the threshold) took precision to 100% with no loss of recall.
No unit test would have caught that, because nothing was broken. It took a suite that graded the system's judgment rather than its behaviour. That's the argument for building evals before you think you need them.
Production hygiene
The boring parts, which are the parts that decide whether this survives contact with production:
Structured contracts. Every upstream response crosses a zod boundary. A malformed payload fails loudly here, rather than silently becoming a plausible hallucination three tool calls later. Contract violations are reported as contract violations, not disguised as network blips.
Retries. Exponential backoff with jitter, on transient failures only (5xx, 429, timeouts). A 400 is not retried — retrying a 400 is just being wrong twice. Jitter matters: without it, a fleet of retrying clients wakes up in lockstep and stampedes an upstream that's already struggling.
Timeouts. An agent blocked forever on a hung socket is worse than one that fails fast, because nothing upstream can distinguish "thinking" from "dead".
Idempotent reads, cached. METARs update hourly. A chatty agent asking about CYOW eight times in one turn costs one upstream call, not eight.
Tracing. One JSON line per tool call to stderr — trace id, tool, duration, cache hit, outcome, and for assessments the category, confidence, and gate decision. Stderr, never stdout: stdout is the MCP transport, and writing to it corrupts the protocol. After the fact you can ask "how often did we gate?" and "did confidence track correctness?" without re-running anything.
Tool errors, not crashes. A tool that throws into the transport takes down every other tool with it. Failures come back as
isErrorwith a reason the model can act on.Pure core. Categorization, confidence, and the gates have no network, no clock, and no model in them. That's why they can be evaluated exhaustively — all the nondeterminism lives at the edges.
Tools
Tool | Purpose |
| Flight category + confidence + escalation gate. The one that matters. |
| Current observations, normalized. |
| Terminal aerodrome forecasts. |
| Resolve a place name to an ICAO identifier. |
Running it
npm install
npm test # 43 unit tests
npm run eval # 15 golden cases, graded — fails the build on a recall miss
npm run build
npm start # MCP server over stdioRegister with any MCP client:
{
"mcpServers": {
"aviation": {
"command": "node",
"args": ["/absolute/path/to/aviation-mcp/dist/index.js"]
}
}
}Then ask it "what are conditions at CYOW, and should I trust the answer?"
Notes on the upstream
aviationweather.gov is a free public service with an undocumented contract, which is to say it is like every other integration. Visibility arrives as a number (15), a string with a plus ("10+"), or a fraction ("1 1/2"). Wind direction is "VRB" when it's variable. None of this is in any spec; all of it is discovered by hitting the API and watching things break. It's normalized once, in normalize.ts, where it's tested — not in six places downstream, and not by hoping the model figures it out.
Layout
src/
index.ts MCP transport wiring. Thin on purpose.
tools.ts Tool definitions + handlers. Uniform shape: validate, trace, call, normalize.
assess.ts Categorization, confidence, and the escalation gates. Pure functions.
client.ts HTTP: retries, backoff, timeouts, TTL cache.
normalize.ts Upstream's bad habits → our contract.
schemas.ts zod contracts.
logger.ts Structured traces.
evals/
cases.ts 15 golden cases, frozen fixtures.
run.ts Graded harness: accuracy, gate precision, gate recall.
test/ 43 unit tests.License
MIT.
Available Tools
4 toolsassess_conditionsAssess flight conditions, with escalationA
Assess current flight conditions at an airport. Returns a flight category (VFR/MVFR/IFR/LIFR), a confidence score, the specific observations behind the call, and a requiresHumanReview flag. IMPORTANT: when requiresHumanReview is true, do not present the category as settled — the conditions are near a category boundary, the report is missing data, significant weather is present, or sources disagree. Surface the reviewReasons and hand off to a person.
| Name | Required | Description | Default |
|---|---|---|---|
| station | Yes | A single ICAO station identifier, e.g. CYOW. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden, and it does substantial work: it discloses the returned fields (category, confidence, underlying observations, requiresHumanReview) and the concrete failure modes that trigger review (boundary proximity, missing data, significant weather, disagreeing sources). It stops short of stating permission/auth needs or the fact that this is a non-mutating read.
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 action and outputs, then the escalation rule flagged with an explicit IMPORTANT marker. Every sentence earns its place and nothing is repeated from 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 must describe returns, and it does so thoroughly, including the escalation contract. Missing only secondary details such as source freshness, whether it is purely read-only, and any rate or auth constraints.
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% and the single 'station' parameter is fully documented in the schema with a pattern and example. The description's 'at an airport' adds only light context, so the baseline 3 for high schema coverage 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 ('Assess current flight conditions at an airport') and enumerates the outputs, which implicitly distinguishes it from the raw-data siblings get_metar and get_taf. Differentiation is implied by the assessment/interpretation framing rather than stated outright, so it falls short of a 5.
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 strong conditional guidance for the output case ('when requiresHumanReview is true, do not present the category as settled... hand off to a person'), but never says when to choose this tool over get_metar/get_taf or search_stations. Usage selection guidance is implied at best.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_metarGet current weather observationsA
Current METAR observations for one or more airports, normalized into a structured schema. Use this when you need the raw current conditions. If you need a judgment about whether conditions are flyable, use assess_conditions instead — it will tell you when it is not sure.
| Name | Required | Description | Default |
|---|---|---|---|
| stations | Yes | ICAO station identifiers, e.g. ['CYOW', 'KJFK']. Max 20. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full disclosure burden; it does add real value by saying results are normalized into a structured schema rather than raw METAR text. However it says nothing about error behavior for invalid or unknown ICAO codes, missing/stale observations, or rate limits, which matters for a data-fetch tool. Adequate but with clear gaps.
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 short sentences, zero filler: what it returns, when to use it, and which sibling to use instead. The routing information is front-loaded rather than buried.
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 single-parameter read tool with no output schema or annotations, the description covers purpose, scope, and sibling routing, which is most of what an agent needs to call it correctly. What's missing is any hint about the returned condition fields or how failures (unknown station, no current observation) surface, though the absence of an output schema limits how much is required.
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% and the single 'stations' parameter is fully documented in the schema (ICAO pattern, max 20). The description's 'one or more airports' merely restates the array semantics already in the schema, adding no new syntax or format detail. Baseline 3 applies when the schema does the heavy lifting.
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 ('Current METAR observations'), the scope ('one or more airports'), and the output form ('normalized into a structured schema'). It also explicitly separates itself from the sibling assess_conditions, so an agent can route without opening either schema.
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 both a positive condition ('when you need the raw current conditions') and an explicit alternative with the condition that selects it ('if you need a judgment about whether conditions are flyable, use assess_conditions instead'). Nothing about the raw-vs-interpreted split 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.
get_tafGet terminal aerodrome forecastsA
Terminal aerodrome forecasts (TAFs) for one or more airports. Forecasts, not observations — use get_metar for what the weather is doing right now.
| Name | Required | Description | Default |
|---|---|---|---|
| stations | Yes | ICAO station identifiers. Max 20. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden, and it does disclose the core distinction (forecasts not observations). However, it omits other behavioral traits such as rate limits, data recency, or failure modes, which is acceptable but not rich context.
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 short sentences with zero waste, and the key distinction (forecast vs observation) is front-loaded in the second sentence after the resource name.
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?
The tool is simple (one parameter, no output schema), and the description covers what it returns and how it differs from get_metar. It is complete enough for correct invocation, though it could add minor context about data output format.
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 the stations parameter (ICAO identifiers, max 20). The description adds no additional syntax or format details beyond confirming the plural-airports scope, which the schema already implies.
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 (get) and resource (terminal aerodrome forecasts), and explicitly disambiguates from the sibling get_metar by contrasting forecasts vs observations. An agent can distinguish this tool from get_metar without opening either schema.
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?
The description explicitly names the alternative tool (get_metar) and the condition that selects it ('use get_metar for what the weather is doing right now'), giving clear when-to-use guidance rather than leaving the choice implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_stationsLook up airport stationsA
Find weather-reporting stations by name or partial ICAO identifier. Use this to resolve a place name to an ICAO id before calling the other tools.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Station name or partial ICAO id, e.g. 'Ottawa' or 'CY'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden and it does disclose the role as an identifier-resolution step. However, it says nothing about match behavior (exact vs fuzzy, multiple results, result limit) — relevant for a partial-match search — so the behavioral picture is only partially complete.
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, zero waste: the first states what it does, the second gives the workflow position. Front-loaded and appropriately sized.
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 one-parameter lookup with no output schema, the description covers purpose and workflow placement adequately. The remaining gap is what matches look like and whether multiple stations can be returned, which an agent would value.
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% and the single parameter is fully documented in the schema with examples and length constraints. The description repeats the same information and adds no syntax or format detail beyond the schema, so 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 (find) and resource (weather-reporting stations) with the matching mechanism (by name or partial ICAO identifier). It is clearly distinguishable from get_metar/get_taf/assess_conditions, which consume rather than resolve identifiers.
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 states when to use it: 'to resolve a place name to an ICAO id before calling the other tools.' It names the dependency relationship with siblings, 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.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v1.0.0- First observed
assess_conditions - First observed
get_metar - First observed
get_taf - First observed
search_stations
TDQS
Scored across 4 tools
Each tool has a clearly distinct purpose: search_stations resolves identifiers, get_metar fetches raw observations, get_taf fetches forecasts, and assess_conditions provides a judgment. The descriptions explicitly differentiate get_metar vs get_taf and assess_conditions, eliminating overlap.
All tool names follow a consistent verb_noun pattern (search_stations, get_metar, get_taf, assess_conditions) with snake_case throughout. No deviations or mixed conventions.
With 4 tools, the set is minimal but perfectly scoped for aviation weather needs. Each tool has a clear, non-redundant role, and the count avoids bloat.
The core aviation weather workflow (resolve station, get current/forecast weather, assess conditions) is fully covered. However, the absence of tools for historical weather, PIREPs, or other advisories leaves minor gaps that an agent might need to work around.
Maintenance
Related MCP Connectors
Read-only airport delay, weather, and 24h forecast tools for AI assistants. Airport-level only.
Aircraft intelligence for AI agents: valuations with uncertainty bands, FAA registry lookups, cost of ownership, comparable aircraft, fleet search, airworthiness directives and STCs, market metrics and forecasts, verified value reports, pre-buy diligence checklists, logbook search and a watchlist. 38 tools; free tier with OAuth or a Windsock API key.
US weather & geo for AI agents: forecasts, alerts, earthquakes, elevation, geocoding. No keys.
US weather & geo for AI agents: forecasts, alerts, earthquakes, elevation, geocoding. No keys.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProvides real-time access to official aviation weather data including METARs, TAFs, and PIREPs directly from aviationweather.gov. It enables users to query airport observations, forecasts, and pilot reports through natural language within Claude.-
- AlicenseAqualityDmaintenanceProvides real-time US weather data for AI assistants via MCP, including current conditions, forecasts, alerts, severe weather outlooks, radar, upper-air analysis, and surface analysis. Supports optional personal weather station integration.94ISC
- AlicenseNot gradedqualityDmaintenanceProvides access to aviation weather data from aviationweather.gov, enabling LLMs to fetch and analyze METAR, TAF, PIREPs, AIRMETs, and other aviation weather information.6 npm6MIT
- AlicenseAqualityDmaintenanceProvides aviation weather briefings including METARs, TAFs, PIREPs, SIGMETs, and NWP forecasts, enabling Claude to fetch and display real-time and forecast weather data for airports and routes worldwide.86 npm3MIT