travel-trends-mcp
Server Details
European tourism & travel-disruption MCP: trip risk, live events, Eurostat panels, RO county data.
- Status
- Healthy
- Uptime
- 100.0% over 76 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
TDQS
Scored across 8 tools
Most tools map to distinct jobs: one-off assessment, ongoing watch, stored update log, live diff, silence explanation, event browsing, daily briefing, and tourism stats. Some adjacent pairs (assess_trip vs watch_trip’s initial assessment, whats_changed vs get_trip_updates_since) require reading the descriptions, but the descriptions explicitly route between them.
All names are snake_case and readable, but the convention is mixed: most are verb_noun (assess_trip, list_events, watch_trip), while country_briefing/country_tourism_profile are noun phrases and whats_changed is an interrogative phrase. Not chaotic, but not a single predictable pattern.
Eight tools is well within the appropriate range and each covers a distinct workflow in the travel-risk lifecycle. No obvious filler or duplicate tool.
Core workflows are covered: one-off assessment, monitoring creation, stored updates, live change diff, silence explanation, event browsing, daily briefing, and country tourism data. Minor gaps remain around managing monitored trips (no list/get-all-trips or early stop/delete, with auto-expiry documented), but no agent dead end for stated purposes.
Available Tools
8 toolsassess_tripARead-onlyIdempotentInspect
Assess one trip: current disruption status for its destinations and dates.
Use this tool when the user asks whether a specific trip is affected by
strikes, weather, transport disruptions or other travel risks.
Give the destinations and the travel window (date_from/date_to,
YYYY-MM-DD). Destinations are the EU-27 ISO2 codes (Greece = "EL") PLUS the
non-EU27 countries we actively monitor: Norway ("NO", rail via Entur, live),
the United Kingdom ("UK" or "GB", transit via TfL, live), and Switzerland
("CH", rail via SBB — key-pending, so it is reported as a declared blind
spot until the feed is keyed, never a false all-clear). A code we do not
monitor is rejected with {"error": "unknown_country"} rather than silently
all-cleared. Returns a Decision-Support answer, not raw data:
* travel_status: NORMAL | MINOR_DISRUPTION | MAJOR_DISRUPTION;
* actionable_lines: per-event DECISION-IMPACT guidance — what the
disruption means for THIS trip and what to do (e.g. "affects regional
trains, not airports -> take a road airport transfer, leave ~30 min
earlier"), or a clearly-labelled "nothing material" line when calm;
* confidence: a LABELLED model output (coverage/corroboration/recency/
blind-spots blend, not a probability) — read its caveats;
* sources_checked: proof of what was monitored (sources_ok, blind spots);
* events + caveats.
Sub-floor noise (a deep, far-field seismic blip) is omitted; calm is a
monitoring result for the window, never an invented forecast. Invalid
inputs return an explicit {"error": ...}; nothing is fabricated.
Top-level MCP-facing structure (additive; existing fields preserved):
* presentation: a three-section block — affects_your_trip[] (each
item with verified_sources[] as display-ready names, source_count,
corroborated flag (≥2 distinct sources), an honest for_you line
bound to destinations+dates only, report_url, first_detected_at,
last_verified_at); doesnt_affect_your_trip (the proof-of-work
pile — shown[] of {headline, reason_excluded}, additional_checked_count,
summary_line, total_checked); next_steps[] (deterministic — re-check
date, aviation-handoff watch when blind spot, per-active monitor URLs);
* track_record_ref: lean {window_days, flagged, ended, still_active,
monitoring_since, url} — numbers + URL only, no narrative;
* suggested_next_call: {tool, context} — the suggested follow-up
(watch_trip) when the user wants continued monitoring.
These exist so an LLM consumer can quote verbatim — every fact is
traceable to a named source or an input field, never invented.
Destinations also accept natural input: country names ('Spain', 'España',
'Spania'), IATA airport or city codes ('ALC', 'TSR', 'LON'), city names in
any common spelling ('Alicante'/'Alacant', 'București'/'Bucharest',
'München'/'Munich') and major rail stations ('Alicante Terminal', 'Gare de
Lyon'), resolved deterministically from local datasets (exact match after
Unicode folding — never fuzzy). The response discloses every mapping in
'resolved_locations' ([{input, canonical_name, country, lat, lon, type,
source, confidence}]); the legacy 'resolved' list is kept. A token that
cannot be placed is returned in 'unresolved_locations' with suggestions;
if at least one other token resolved, the verdict is still computed on the
resolved countries and marked 'degraded' (reason + missing tokens, plus a
caveat) — never a silent downgrade. When nothing resolves the call is
rejected with {'error': 'unknown_destination', 'unresolved_locations':
[...]}; a token in a country we do not monitor is rejected with
{'error': 'unknown_country'}.
Regional scope (weather): when the source publishes warning AREAS
(Meteoalarm areaDesc + EMMA_ID), each cited event carries
region_scope {level: region | no-match | country, matched[], places_checked,
method} — a NAME match between the areas and your resolved places / their
region and province (no geometry: Meteoalarm publishes no polygons). The
country-level travel_status is unchanged; travel_status_regional is the
status without the events whose areas name none of your places, and a
caveat says so. Weather events without area detail say "country level".
Optional `legs`: the trip as segments with a travel MODE —
[{"from": "OTP", "to": "Valencia", "mode": "air", "date_from": "...",
"date_to": "..."}, {"from": "Valencia", "to": "Alicante", "mode": "rail"}]
(mode: air | rail | road | sea; leg dates optional, default = the trip
window, must sit inside it). Endpoints are resolved like destinations and
are ADDED to them, so you may pass destinations: [] with legs only. The
answer then carries legs[]: per leg the resolved endpoints, countries,
domains_applicable for its mode (rail sources apply to rail legs, aviation
to air legs; weather/disaster/health/geopolitical/public order to all),
the events that hit THAT leg (a weather event whose areas name neither
endpoint is listed apart in events_not_in_your_regions), its own
travel_status, its own blind_spots and — for air legs — the
aviation_handoff. An unresolved endpoint is an
explicit {"error": "unresolved_leg_endpoint"} with suggestions.
Pass `lang` (e.g. "de", "ro", "pl", "fr", "es", "it"; default English) to
answer in the traveller's language — useful for a traveller
in a country whose language they do not speak. The response then carries a
`localized` block with the status sentence, an honest reassurance line
(calm ONLY when status is NORMAL), the decision-impact lines, AND — never
dropped — the localized caveats + blind_spots. Source-derived free text the
traveller cannot read (an event headline in the source language) is
AI-translated via Gemini and carries the label "AI-translated — verify
against the linked official source"; when no GEMINI_API_KEY is set or a
translation fails, the original source text is kept with an honest note —
never a fake translation. Our own wording falls back to English (flagged in
`localized.fallback_lang_parts`) when no template exists for `lang`; an
unknown `lang` answers in English and says so (`is_known_lang=false`).
Localization NEVER becomes a false all-clear and the aviation handoff is a
SIGNPOST that DISCLOSES the blind spot, not coverage.
Pass `audience` for role-specific operational actions (B2B travel-risk /
duty-of-care): one of "tmc" (travel management company / corporate travel
risk), "hotel", "ota", "tour_operator". The response then carries a
`persona` block: {audience, actions[]} where each action ties an affecting
event to that role's recommended steps (e.g. TMC: flexible-rebooking policy,
reroute inventory, proactive guest comms) — a PURE PROJECTION of the
audience-tagged recommendations already computed per event, each carrying a
`based_on` disclosure of the inputs it used. An unknown audience is reported
honestly with the valid set, never guessed. Omit `audience` for the default
(no persona block).
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | ||
| legs | No | ||
| date_to | Yes | ||
| audience | No | ||
| date_from | Yes | ||
| destinations | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, it discloses output semantics, error cases, degraded-resolution behavior, blind spots, non-fabrication guarantees, localization fallbacks, and persona projection limits. The annotations cover read-only/idempotent safety, while the description adds rich operational context; openWorldHint=false is not contradicted because monitoring is limited to a declared closed set of countries and sources.
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?
The purpose is front-loaded and the long description is organized into readable sections. However, it is heavily over-specified with response-field implementation details, legacy-field notes, and repeated caveats that could be trimmed for a tool-selection description.
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 complex tool with no output schema, the description explains return structure, status enums, confidence caveats, sources checked, error responses, regional scope, legs, localization, and audience behavior. It is complete enough for an agent to invoke the tool correctly and interpret its output.
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 0%, so the description carries full parameter burden and does so thoroughly: destination formats, ISO2 codes, non-EU countries, natural-language resolution, date format, optional legs structure and modes, lang behavior, and audience values. It adds substantial meaning far beyond the bare 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 and resource: assessing one trip's current disruption status for its destinations and dates. It clearly distinguishes this from raw event-list tools by saying it returns a Decision-Support answer, not raw data.
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 to use it when the user asks whether a specific trip is affected by strikes, weather, transport disruptions, or other travel risks. It also routes continued monitoring to watch_trip via suggested_next_call, but does not explicitly contrast with country_briefing or list_events.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
country_briefingARead-onlyIdempotentInspect
Get today's published daily briefing, pre-formatted for end users.
Use this tool for a general "what is happening today in EU travel"
question that is not tied to one specific trip.
Returns the same payload as the underlying daily briefing artifact:
headline counts, one plain-language headline per active event,
monitoring coverage (sources_ok / blind_spots_count), backtest trust
figures, and a caveats list. Always relay caveats alongside numbers.
Optional ``country`` (EU-27 ISO2 alpha-2, Greece = "EL") narrows the
events list only — headline_counts / monitoring / trust stay
EU-27-wide, as flagged in the returned note. Missing artifact returns
``{"error": "unavailable"}``.
| Name | Required | Description | Default |
|---|---|---|---|
| country | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the read-only, idempotent, non-destructive annotations, the description discloses critical behaviors: the payload structure (headline counts, plain-language headlines, monitoring coverage, trust figures, caveats), the requirement to always relay caveats, the country filtering scope (narrows events only, not metrics), and the exact error response for a missing artifact. This is rich, transparent 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?
The description is dense but every sentence earns its place. It front-loads the core purpose, then adds usage guidance, return payload details, a critical caveat-relaying instruction, parameter semantics, and an error case. No filler or redundancy; structure is logical and scannable.
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 must explain return values—it does so explicitly, including the key components and the caveats list. It also covers the only parameter, the error condition, and the global vs. country-wide scope nuance. For a tool with one optional parameter and no output schema, this is fully complete.
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 provides almost no param description (0% coverage), so the description carries the full burden. It explains the optional country parameter with format (EU-27 ISO2 alpha-2), gives an example (Greece = "EL"), and precisely describes the behavioral effect (narrows events list only; headline_counts/monitoring/trust stay EU-27-wide). This is exemplary parameter documentation.
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?
Description starts with a specific verb 'Get' and identifies the exact resource: 'today's published daily briefing, pre-formatted for end users.' It also distinguishes itself from trip-specific tools by stating it is 'not tied to one specific trip,' directly addressing the sibling context.
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 this tool: 'for a general "what is happening today in EU travel" question that is not tied to one specific trip.' It implicitly excludes trip-specific scenarios but does not name alternative tools explicitly. The clear context and exclusion provide strong guidance, falling just short of naming specific alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
country_tourism_profileARead-onlyIdempotentInspect
Tourism profile for one EU-27 country — a decade of Eurostat data.
Use this tool for questions about a country's tourism statistics,
seasonality or visitor mix, not for live disruptions.
Pure projection of the published artifacts (countries/<code>.json +
competitiveness.json): yearly nights/arrivals totals with YoY, average
stay, seasonality (peak month and peak-to-mean ratio, formula disclosed),
domestic vs foreign visitor share, recovery vs 2019, growth vs the EU
average, and computed competitiveness insights (each labeled with its
basis). Every number is computed from the same public dataset the site
serves — nothing narrated, nothing estimated; links carry the citable
page + raw JSON. `code` is EU-27 ISO2 (Greece = "EL"). Unknown country ->
{"error": "unknown_country"}; missing artifact -> {"error": "unavailable"}.
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint, idempotentHint), the description adds critical behavior: it is a 'pure projection of the published artifacts,' discloses that 'every number is computed from the same public dataset,' provides error formats for unknown country ('unknown_country') and missing artifact ('unavailable'), and notes that links carry citable pages plus raw JSON. This is rich contextualization with no contradiction.
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?
The description is information-dense yet each sentence earns its place: purpose, usage guideline, data source, metric list, parameter format, and error handling. It is front-loaded with the primary function and contains no filler or tautology.
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?
Given there is no output schema, the description enumerates all return aspects: YoY totals, average stay, seasonality with peak-to-mean ratio, visitor share, recovery vs 2019, growth vs EU average, and competitiveness insights. It also documents data provenance, error cases, and link details, making it self-sufficient for the agent.
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?
With schema description coverage at 0%, the description fully compensates by explaining that `code` is an EU-27 ISO2 code and gives the concrete example 'Greece = "EL"'. It also clarifies behavior for invalid or missing artifacts, which helps the agent invoke the tool correctly.
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 opens with 'Tourism profile for one EU-27 country — a decade of Eurostat data,' which is a specific verb+resource statement. It also explicitly differentiates from siblings by saying 'Use this tool for questions about a country's tourism statistics, seasonality or visitor mix, not for live disruptions,' making its scope unmistakable.
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?
It clearly states when to use the tool (for tourism statistics, seasonality, visitor mix) and when not to use it (not for live disruptions). However, it does not name alternative tools for live disruptions, though the sibling list includes candidates like list_events, so the guidance is not fully explicit on alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
explain_silenceARead-onlyIdempotentInspect
Explain why a watched trip has produced no updates.
Use this tool when the user asks why they have not heard anything about
a watched trip. Returns {recheck_count, last_checked} (proof the trip
was actively monitored),
{suppressed:[{what, domain, country, score, floor, reason}]} (what we saw
for your destinations and dropped below the disclosed relevance floor —
e.g. a deep quake at modelled felt-intensity 3.39 < floor 4.0),
{confidence_during_window} (same recency input as assess_trip), and
{blind_spots:[{domain, country, note}]} — domains/countries we do NOT
monitor live, so silence there is NOT a guarantee (e.g. aviation-IT blind
spot => silence does not cover flights). Also {coverage_classes:[{class,
domain, label, monitored_in, not_monitored_in, via, statement}]} — per KIND
of disruption (on-track incidents and local rail operations, individual
flight delays, local road closures, country-level weather warnings…) where
it is observable to us and where NO configured source watches it, so "your
train was stopped by an incident only a local blog reported" is explainable
— plus {sources_consulted, sources_pending} per destination.
`since` optionally scopes the recheck window. Id is regex-validated;
unknown -> {"error": "not_found"}, malformed -> {"error": "invalid_trip_id"}.
| Name | Required | Description | Default |
|---|---|---|---|
| since | No | ||
| trip_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description adds substantial context beyond them: full return-field semantics including the disclosed relevance floor, blind spots where silence is explicitly NOT a guarantee, and error behavior for unknown vs malformed ids. This is exactly the extra context annotations cannot 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?
The purpose and trigger are front-loaded and waste nothing, but the remainder is a dense run-on enumerating return fields with inline brace notation and parentheticals nested three levels deep. Since no output schema exists the content is justified, yet the structure is hard to scan.
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 full burden of describing returns and does so across all four response sections plus per-destination source lists. Combined with the error cases and the `since` scoping note, an agent has everything needed to call it and interpret the result.
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 0%, so the description must carry the load — it explains that `since` "optionally scopes the recheck window" and that trip_id is regex-validated with distinct not_found and invalid_trip_id errors. It stops short of giving the actual regex or the timestamp format for `since`, so a 4 rather than a 5.
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 object ("Explain why a watched trip has produced no updates") that is unmistakably distinct from siblings like get_trip_updates_since (which returns updates) and assess_trip (which assesses risk). An agent can route on the first sentence alone.
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 an explicit trigger: "Use this tool when the user asks why they have not heard anything about a watched trip." It also clarifies the relationship to assess_trip (same recency input), but never states when NOT to use it or which sibling to prefer when the user wants actual updates rather than silence.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_trip_updates_sinceARead-onlyIdempotentInspect
The watched-trip updates log filtered to entries AFTER since.
The notification payload: everything logged for the trip strictly after
the `since` ISO-8601 timestamp (the user's last-seen time), oldest-first.
Returns {trip_id, since, new_update_count, updates}. Use this tool to
fetch the stored update entries the user has not seen yet; for a live
recomputed diff, use whats_changed instead. An empty `since` returns the whole
log. Id is regex-validated (^trip-[a-z0-9-]+$); unknown id ->
{"error": "not_found"}, malformed id -> {"error": "invalid_trip_id"}.
| Name | Required | Description | Default |
|---|---|---|---|
| since | Yes | ||
| trip_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses significant behavioral details beyond the annotations: returns entries 'strictly after the `since` timestamp, oldest-first', describes the response shape, and specifies error behaviors for unknown and malformed IDs. Annotations already declare read-only and idempotent, and the description adds no contradictions.
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?
The description is well-structured and concise, leading with the core purpose and then covering notable behaviors and edge cases in a compact, readable form. Every sentence adds value without 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?
Even though there is no output schema, the description explicitly states the return object ({trip_id, since, new_update_count, updates}), error responses, and validation rules. Combined with the detailed parameter semantics and usage guidance, the description is fully self-contained for an AI agent.
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 schema provides no descriptions, but the description fully compensates: it defines `since` as 'ISO-8601 timestamp (the user's last-seen time)' and the empty-since behavior, and specifies the `trip_id` format via regex and associated error messages.
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 clearly states the tool's purpose: 'The watched-trip updates log filtered to entries AFTER `since`.' It specifies the resource (trip updates log) and the action (fetch filtered by since), and explicitly distinguishes from the sibling tool whats_changed, which provides a live recomputed diff.
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 provides explicit usage direction: 'Use this tool to fetch the stored update entries the user has not seen yet; for a live recomputed diff, use whats_changed instead.' This states when to use and points to the alternative. It also covers edge cases for empty `since` and validation errors.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_eventsARead-onlyIdempotentInspect
List detected travel-disruption events for EU-27 tourism.
Use this tool to browse or filter current disruption events across
countries; for a question about one specific trip, use assess_trip.
Events are deterministic, rule-based detections over published live
snapshots and monthly indicators — thresholds are disclosed in each
event record; nothing is model-generated here. Filters: status (e.g.
"active"/"resolved"), country (EU-27 ISO2, Greece = "EL"), domain
(e.g. "weather", "aviation"), min_severity on the ordered scale
info < watch < warning < severe. Returns {count, events, filters};
on missing index returns {"error": "unavailable"}.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | No | ||
| status | No | ||
| country | No | ||
| min_severity | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive. The description adds meaningful behavioral context: events are deterministic rule-based detections, thresholds are disclosed in each record, nothing is model-generated, and missing index yields a specific error format. This goes well beyond the annotations.
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 dense sentences with zero filler. The first sentence states purpose, the second provides usage guidance, the third explains data provenance, and the fourth covers filters and return format. Every sentence adds value and is well-organized.
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?
Despite no output schema, the description specifies the return shape ({count, events, filters}) and the error case. It covers all parameters, the underlying data source, and filters. For a list tool with this complexity, the description is complete and leaves no significant gaps.
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 has 0% description coverage and no enums, so the description carries the full burden. It clearly explains each filter: status with examples, country as EU-27 ISO2 (Greece = 'EL'), domain with examples, and min_severity with an explicitly ordered scale (info < watch < warning < severe). This is exactly the missing parameter semantics.
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 opens with a specific verb+resource+scope: 'List detected travel-disruption events for EU-27 tourism.' It clearly distinguishes from siblings by positioning this as the browse/filter tool and explicitly directing trip-specific questions to assess_trip.
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?
Explicit usage guidance: use for browsing/filtering across countries, and 'for a question about one specific trip, use assess_trip.' This directly tells the agent when to prefer an alternative, satisfying the when-to-use and when-not-to-use criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
watch_tripAInspect
Start monitoring one trip for disruption changes over time.
Use this tool when the user wants ongoing monitoring of a trip rather
than a one-off assessment (for a one-off answer, use assess_trip).
Persists the trip as a monitored object and returns its initial assessment
plus a random, unguessable trip_id AND a one-time `owner.owner_token`.
Store BOTH: the trip_id is the (public, shareable) URL handle, the
owner_token is the private key needed to change the trip's label or
webhook later. There is no stop call: monitoring ends by itself the day
after date_to.
CREATE vs REFRESH: called with just destinations+dates it CREATES a new
trip every time (it does NOT dedupe on identity — that is deliberate, so
nobody can reach your trip by guessing your itinerary). To update an
existing trip (change its label or webhook), call again passing BOTH its
`trip_id` and `owner_token`; a missing/wrong token is rejected. Each
pipeline run then re-evaluates the trip and appends an update ONLY when
something materially changes (a new/cleared event, a severity/status shift,
or a travel_status change) — never on a calm tick.
Args: destinations — EU-27 ISO2 codes (Greece = "EL") plus the non-EU27
countries we monitor: Norway "NO" (Entur, live), United Kingdom "UK"/"GB"
(TfL, live), Switzerland "CH" (SBB, key-pending → declared blind spot until
keyed); date_from/date_to (YYYY-MM-DD); optional label. An unmonitored code
is rejected with {"error": "unknown_country"} rather than a false all-clear.
Returns {trip_id, assessment, created_at}; invalid inputs return an explicit
{"error": ...}.
Destinations also accept natural input: IATA airport codes (e.g. 'TSR',
'AMS', 'ZRH') and major city names (e.g. 'Timișoara', 'Amsterdam',
'Zürich', 'London'), resolved deterministically to a monitored country
code. The initial assessment includes a 'resolved' list
([{input, country, kind}]) disclosing how each token was mapped
(e.g. 'TSR -> RO via iata-airport'). A token that resolves to a country we
do not monitor is rejected with {'error': 'unknown_country'}; a token we
cannot resolve at all is rejected with
{'error': 'unknown_destination', 'tokens': [...]} — we reject not guess.
Pass `lang` (e.g. "de", "ro", "pl"; default English) to localise the
initial assessment into the traveller's language: the returned
assessment carries the same `localized` block as assess_trip (honest
reassurance, AI-translated-and-LABELLED source text, and the localized
caveats + blind_spots that are never dropped). Localization never becomes a
false all-clear; the aviation handoff discloses the blind spot, not coverage.
Pass `audience` ("tmc" | "hotel" | "ota" | "tour_operator") for role-specific
operational actions — the initial assessment then carries the same `persona`
block as assess_trip (audience + per-event role actions, projected from the
audience-tagged recommendations). Built for the B2B travel-risk buyer.
Pass `notify_webhook_url` (https only) to get PUSH delivery: on every
MATERIAL change the radar POSTs the update record (summary, status
transition, event report URLs) to your URL, signed HMAC-SHA256 over the
raw body (header X-TravelTrends-Signature: sha256=<hex>). The response
then includes `notify.secret` — shown ONLY once, never published; store
it to verify signatures. To change or remove the webhook later, re-call
with the trip_id + owner_token and the new notify_webhook_url (or "" to
remove delivery). After 5 consecutive delivery failures the webhook is
disabled with an honest notify_disabled entry in the trip's updates log.
Non-https or private-network URLs are rejected with
{"error": "invalid_webhook_url"}.
Optional `legs` (same shape and semantics as in assess_trip) are persisted
with the trip; legs[] appears in the assessment returned here. The 6-hourly
radar check re-resolves the stored legs and their modes feed its decision
lines; whats_changed reports the trip-level delta and does not carry a
legs block.
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | ||
| legs | No | ||
| label | No | ||
| date_to | Yes | ||
| trip_id | No | ||
| audience | No | ||
| date_from | Yes | ||
| owner_token | No | ||
| destinations | Yes | ||
| notify_webhook_url | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare non-idempotent, non-read-only, open-world, but the description explains WHY: no dedupe on identity, deliberate, so trips cannot be guessed. It further discloses the owner_token as a non-recoverable private key, HMAC-signed webhook delivery with a one-time notify.secret, the 5-failure auto-disable, and rejection of private-network URLs — none of which is in the annotations.
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 purpose and the assess_trip handoff, then organized into labelled blocks (CREATE vs REFRESH, Args, Returns, then lang/audience/webhook/legs). It is long and the localization paragraph restates assess_trip's `localized` block at some length, but every section maps to a caller decision, so the density is justified rather than padded.
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?
No output schema exists, yet the description documents the return shape ({trip_id, assessment, created_at}), the additional notify.secret, the resolved list inside the assessment, and the full error vocabulary (unknown_country, unknown_destination, invalid_webhook_url). For a 10-parameter mutation tool with a side-effecting webhook, nothing an agent needs to call it 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 coverage is 0% across 10 parameters, so the description carries the full burden and does: destinations (ISO2 plus IATA/city resolution and the EL/UK/GB/CH edge cases), date formats, label, lang, audience with its four allowed values, notify_webhook_url constraints, legs semantics, and trip_id+owner_token pairing. Error contracts for unresolvable and unmonitored codes ('we reject not guess') are spelled out.
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 ('Start monitoring one trip for disruption changes over time') and immediately distinguishes the scope from the sibling: ongoing monitoring vs. a one-off answer. An agent can tell this apart from assess_trip 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?
Explicit when-to-use ('ongoing monitoring ... rather than a one-off assessment'), names the alternative ('for a one-off answer, use assess_trip'), and adds a detailed CREATE vs REFRESH rule that tells the agent exactly how to avoid duplicating trips. It also states there is no stop call and that monitoring self-expires the day after date_to.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whats_changedARead-onlyIdempotentInspect
Report only what changed for a watched trip since a checkpoint.
Use this tool when the user asks for news on a trip already registered
with watch_trip; for the stored notification log rather than a live
diff, use get_trip_updates_since. Recomputes the
trip's current assessment and diffs it against the checkpoint at/just-
before `since` (or the last evaluation when `since` is omitted). Returns
{material, summary, added_events, removed_events, changed_events,
previous_travel_status, travel_status, confidence_from, confidence_to}.
`summary` is a plain-language line ('Since your last check: rail strike
CONFIRMED (was: announced); a road closure cleared; confidence 63->71%').
A non-material tick returns material=False with a clearly-flagged 'No
material change' summary — never invented churn. `since` is an optional
ISO-8601 timestamp (e.g. the user's last-seen time). Id is regex-validated
(^trip-[a-z0-9-]+$); unknown id -> {"error": "not_found"}, malformed id ->
{"error": "invalid_trip_id"}.
The response also forwards the presentation blocks from the current
assessment so the LLM consumer has full context alongside the delta:
presentation (affects_your_trip / doesnt_affect_your_trip / next_steps),
track_record_ref (90-day counts + URL), and suggested_next_call
(the suggested follow-up action). Forwarded in both material=True and
material=False branches; absent if upstream did not compute them
(legacy code paths) — never fabricated.
`audience` (optional: tmc | hotel | ota | tour_operator) attaches the
same `persona` block as assess_trip/watch_trip to the change alert —
audience-tagged actions for the events currently affecting the trip, so
the alert itself carries the operational next step. Unknown audience ->
honest error listing valid_audiences.
| Name | Required | Description | Default |
|---|---|---|---|
| since | No | ||
| trip_id | Yes | ||
| audience | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, and the description adds substantial behavioral context: recomputation and diffing, non-material ticks with 'never invented churn', error responses for unknown/malformed IDs, forwarded presentation blocks with 'never fabricated' caveats, and honest errors for unknown audiences. No contradictions with annotations.
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?
The description is longer than average, but it is front-loaded with the core purpose and each paragraph adds necessary details about return values, errors, forwarded context, and audience behavior. It could be tightened slightly, as some return-field details are repeated across paragraphs, but overall it is well structured and information-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 and three parameters, the description is exceptionally complete: it covers the return object shape, material/non-material branches, error semantics, optional parameters, alternative tools, and edge-case behavior. It leaves little ambiguity for an agent selecting and invoking the 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 0%, so the description carries the full burden for explaining parameters. It explains trip_id via regex validation and error cases, since as an optional ISO-8601 timestamp used as the checkpoint, and audience as an optional tmc/hotel/ota/tour_operator value with defined behavior. This goes well beyond the bare 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?
The description opens with a specific verb and resource: 'Report only what changed for a watched trip since a checkpoint.' This precisely defines the tool's scope and clearly differentiates it from siblings, even naming get_trip_updates_since as the alternative for stored notification logs.
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?
Explicit usage guidance is provided: 'Use this tool when the user asks for news on a trip already registered with watch_trip; for the stored notification log rather than a live diff, use get_trip_updates_since.' This states both when to use and when not to use the tool, naming a specific alternative.
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.
2 tool updates
- Changed
assess_trip1 field changed- added
Input schema / properties / legsAdded value: +{ + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Legs" +}
- Changed
watch_trip1 field changed- added
Input schema / properties / legsAdded value: +{ + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Legs" +}
1 tool update
- Changed
watch_trip2 fields changed- added
Input schema / properties / owner_tokenAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Owner Token" +} - added
Input schema / properties / trip_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Trip Id" +}
8 tool updates
- First observed
assess_trip - First observed
country_briefing - First observed
country_tourism_profile - First observed
explain_silence - First observed
get_trip_updates_since - First observed
list_events - First observed
watch_trip - First observed
whats_changed
Related MCP Connectors
Aggregated travel MCP — flights, tours, activities, price checks, visas, and more.
EU/UK tenders, EU law, funding, medicines, drug shortages, recalls, sanctions, CVE, CERT, holidays.
Geopolitical OSINT: sanctions, NOTAMs, maritime warnings, outages, conflict records with sources
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEU Crop Intelligence MCP Server — Yield forecasts, weather analysis, and phenology models for 15 countries. AI agent-native, multi-source intelligence (NASA POWER, Eurostat, Open-Meteo).MIT
- AlicenseAqualityBmaintenanceMCP server for Eurostat statistics, enabling seamless search, query, and analysis of over 8,900 EU datasets with support for SDMX, DuckDB SQL, NUTS regional filtering, and CSV export.121MIT
- AlicenseNot gradedqualityDmaintenanceAgent-ready economic, market & geo-health intelligence — 163 MCP tools, 155 driver-backed indices.MIT
- AlicenseAqualityDmaintenanceMCP server for EU company and business data. 9 tools: company search (GLEIF, 2M+ entities), LEI lookup, corporate structures (parent/subsidiaries), trade register search, EU VAT validation (VIES), GDP, unemployment, inflation, and business demography (Eurostat). All APIs free, no keys required.96MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.