이 MCP로 할 수 있는 일
Assesses travel disruption risk, lists monitored events, provides EU tourism statistics, and supports ongoing trip monitoring.
assess_trip
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: 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 response 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 rather
than guess.
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).
읽기 전용
멱등성
입력 스키마
{'type': 'object', 'title': 'assess_tripArguments', 'required': ['destinations', 'date_from', 'date_to'], 'properties': {'lang': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'title': 'Lang', 'default': None}, 'date_to': {'type': 'string', 'title': 'Date To'}, 'audience': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'title': 'Audience', 'default': None}, 'date_from': {'type': 'string', 'title': 'Date From'}, 'destinations': {'type': 'array', 'items': {'type': 'string'}, 'title': 'Destinations'}}}
watch_trip
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 or stop the trip later.
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"}.
외부 접근 가능
입력 스키마
{'type': 'object', 'title': 'watch_tripArguments', 'required': ['destinations', 'date_from', 'date_to'], 'properties': {'lang': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'title': 'Lang', 'default': None}, 'label': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'title': 'Label', 'default': None}, 'date_to': {'type': 'string', 'title': 'Date To'}, 'trip_id': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'title': 'Trip Id', 'default': None}, 'audience': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'title': 'Audience', 'default': None}, 'date_from': {'type': 'string', 'title': 'Date From'}, 'owner_token': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'title': 'Owner Token', 'default': None}, 'destinations': {'type': 'array', 'items': {'type': 'string'}, 'title': 'Destinations'}, 'notify_webhook_url': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'title': 'Notify Webhook Url', 'default': None}}}