Skip to main content
Glama
nanwer
by nanwer

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
SERPAPI_KEYNoOptional SerpAPI key for hotel, event, and activity search. Get one at https://serpapi.com/manage-api-key

Capabilities

Features and capabilities supported by this server

CapabilityDetails
tasks
{
  "list": {},
  "cancel": {},
  "requests": {
    "tools": {
      "call": {}
    },
    "prompts": {
      "get": {}
    },
    "resources": {
      "read": {}
    }
  }
}
tools
{
  "listChanged": true
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
search_flightsA

🎯 RENDERING DIRECTIVE β€” READ FIRST. When this tool returns 2+ flight offers, you MUST present them as an interactive HTML/React artifact (an Artifacts block, not flowing prose). Each offer is a visually distinct CARD with a prominent "Book on Google Flights" button styled as an HTML button or large rounded link, NOT an inline markdown hyperlink. Plain prose with [text](url) links is NOT acceptable for multi-result responses β€” the user can't click a paragraph. If this call is part of a larger trip-plan response, the trip plan ITSELF should be an artifact and contain the flight cards. Single-result responses may use prose.

Search live flight offers for a given route and date range using Google Flights data.

Returns a ranked list of flight options with prices, airlines, segment details, and total trip durations. Does not book flights, only searches.

Times in the response are local to the departure or arrival airport, with the airport's IATA code attached so the timezone can be derived. Do not perform timezone math on these times without first converting them.

Origin and destination accept 3-letter IATA airport codes (HEL, JFK, LHR) AND city codes (WAS, NYC, LON, PAR, TYO, LAX/QLA, BOS, …). City codes auto-expand to the metro's busiest 3 airports and search them in parallel; results merge under one ranked list (cheaper variant wins on dedup). Use the airport code when the traveler insists on a specific airport. The currency Google Flights returns is determined by the request region and is surfaced in each offer's currency field; do not assume USD.

Filter parameters:

  • max_stops: one of ANY (default), NON_STOP, ONE_STOP_OR_FEWER, TWO_OR_FEWER_STOPS. The names mean "this many stops or fewer".

  • departure_window: a "HH-HH" string in 24-hour local time, e.g. "8-20" to restrict to outbound departures between 8am and 8pm local. Hours are inclusive of the start and EXCLUSIVE of the end β€” "8-20" matches 08:00 through 19:59 local time; a 20:00 or 20:30 departure does NOT match. Applies to the outbound leg only. Google Flights' native filter does not control the return leg.

  • inbound_window: a separate "HH-HH" window for the return leg. Same format and same inclusive-start/exclusive-end semantics as departure_window. Has no effect on one-way searches. When set, offers whose return-leg first segment departs outside this window are filtered out post-hoc.

  • airlines: an optional list of IATA airline codes. Shows offers where AT LEAST ONE of the listed airlines operates ANY segment of the itinerary. For example, ["FI"] returns options operated entirely or partly by Icelandair; it does NOT restrict to Icelandair-only itineraries. Omit or pass null for no airline filter.

Results from identical searches are cached for up to 5 minutes. If the user is about to act on a specific offer, re-run the search before committing to a number.

Dates must be today or future in UTC. The tool rejects past dates with an invalid_input error β€” if a user gives a date that may already be past in their local timezone, advance to the next valid day before calling.

Several fields are commonly null with this data source: baggage_allowance, last_ticketing_date, and seats_available. A null baggage_allowance means "the carrier did not surface this information," not "no checked bag is included." Do not state that a fare excludes checked bags based on a null value.

PRE-CALL ELICITATION: Before calling this tool, ensure the user has expressed preferences on the following. If any are unspecified, ask the user before searching. Do not assume defaults; results vary materially based on these.

  • Baggage: carry-on only, or checked bag needed (affects fare class and final price)

  • Connections: non-stop preferred, or okay with stops (sets max_stops)

  • Time of day: red-eye okay, hard arrival deadlines, preferred outbound departure window (sets departure_window), preferred return departure window (sets inbound_window)

  • Airline preferences: any airlines to prefer (loyalty programs) or avoid (sets airlines)

RESULT PRESENTATION: When returning 2 or more results to the user, render them as an interactive artifact rather than a text list. Each offer is a card showing:

  • Total price, prominent

  • Airlines (IATA codes)

  • Total trip duration and stop count for each leg

  • Departure and arrival times for outbound and inbound, labeled with airport codes

  • A "Book on Google Flights" button linking to the offer's booking_url, opening in a new tab

Sort cards by price ascending. For a single result, prose is fine.

search_cheapest_datesA

🎯 RENDERING DIRECTIVE β€” READ FIRST. When this tool returns 5+ entries, render them as an HTML/React artifact β€” a small price-grid or chart, NOT a long flowing list. For 1-4 entries, prose is fine. The cheapest 1-2 dates should be visually highlighted. Offer to deep-dive into the cheapest date with search_flights once the user picks one.

Find which travel dates are cheapest across a flexible range, using Google Flights data.

Returns a list of (departure_date, return_date, price) entries sorted cheapest first. Does not return flight times, airlines, or layover details β€” for that, use search_flights once the user picks a date.

USE THIS TOOL WHEN: the user is flexible on travel dates and wants to know which dates within a range are cheapest. Typical phrasings: "any week in May", "next month sometime", "around the second week of June", "is it cheaper if I shift my trip a few days?".

USE search_flights INSTEAD WHEN: the user has specific dates and wants flight details, airlines, departure times, layovers, and bookable offers.

The currency Google Flights returns is determined by the request region and is surfaced in each entry's currency field; do not assume USD.

For round-trip date searches, trip_duration (in days) is required β€” it determines each candidate return date. The tool returns a (departure_date, departure_date + trip_duration) pair per result. For one-way, return_date in each result is null.

Filter parameters mirror search_flights:

  • max_stops: one of ANY (default), NON_STOP, ONE_STOP_OR_FEWER, TWO_OR_FEWER_STOPS. "Or fewer" semantics.

  • departure_window: a "HH-HH" string in 24-hour local time, applied to the outbound departure. Hours are inclusive of the start and EXCLUSIVE of the end β€” "8-20" matches 08:00 through 19:59 local time.

  • airlines: an optional list of IATA airline codes. Shows date entries where AT LEAST ONE of the listed airlines operates ANY segment. For example, ["FI"] returns dates with options operated entirely or partly by Icelandair; it does NOT restrict to Icelandair-only itineraries. Omit or pass null for no airline filter.

PRE-CALL ELICITATION: Before calling this tool, ensure the user has expressed:

  • Date range: a clear earliest acceptable departure (start_date) and latest acceptable departure (end_date). If they said "next month" or "sometime in May" without bounds, ask. The wider the range, the slower and noisier the result.

  • Trip duration (round-trip only): the number of nights/days they want to be away. "About 10 days" needs to become a concrete trip_duration integer.

  • What flexibility actually means to the user: are they only flexible on departure date, or also on trip length? If trip length is flexible, run this tool multiple times with different trip_duration values; this tool only varies departure within one duration.

RESULT PRESENTATION: Render the results as a sorted list with the cheapest entries highlighted, or a small date grid if the range is short. Each entry shows the departure date, the return date (if round-trip), and the total price with currency. Lead with the cheapest. Offer to deep-dive into a specific date with search_flights once the user picks one.

search_staysA

🎯 RENDERING DIRECTIVE β€” READ FIRST. When this tool returns 2+ stay offers, you MUST present them as an interactive HTML/React artifact (Artifacts block, not flowing prose). Each stay is a visually distinct CARD with a prominent "Book on Google Hotels" button styled as an HTML button, NOT an inline markdown hyperlink. Plain prose with [text](url) links is NOT acceptable for multi-result responses β€” the user can't click a paragraph. If this call is part of a larger trip-plan response, the trip plan ITSELF should be an artifact containing the stay cards. Single-result responses may use prose.

Search Google's hotel AND vacation rental listings for a city, date range, and party size, returning a ranked unified list of available places to stay.

Returns ranked stay offers β€” each with name, photos, star rating (hotels only), review score, price (per-night and total), top amenities, GPS coordinates, a category badge ("hotel" or "vacation_rental"), per-property OTA price comparison via sources, and a Google Hotels deep link. Does NOT book β€” the booking_url opens the specific property's Google Hotels entity page with the user's check-in/check-out pre-filled, where they can click through to a booking partner.

category selector:

  • "all" (default) β€” fans out to TWO SerpAPI calls in parallel: one for hotels, one for vacation rentals. Merges, dedupes, sorts. Latency is ~3s (parallel, not summed). Costs 2 SerpAPI calls instead of 1 per query β€” burns SERPAPI quota twice as fast.

  • "hotels" β€” only hotel-class properties. One SerpAPI call.

  • "vacation_rentals" β€” only short-term rentals via SerpAPI's aggregation. Surfaces OTAs (Booking.com, Hotels.com, Bluepillow.com, Vrbo.com when available). Airbnb is NOT in Google's aggregation β€” use category="airbnb" for that.

  • "airbnb" β€” bypasses SerpAPI entirely and queries Airbnb directly (via the pyairbnb library). Use this when the user specifically asks for "Airbnb" / "AirBNB" / "stuff on Airbnb". Costs NO SerpAPI quota but is slower and more fragile (Airbnb may block scraping during high traffic). Filter parameters supported: min_bedrooms, min_bathrooms, min_review_score, max_price_per_night. min_rating is ignored (Airbnb listings have no hotel-class star rating).

sources is a per-offer list of (name, price_per_night) entries showing the same property listed across different booking partners. Empty list for hotels in the current data (SerpAPI doesn't surface partner prices for hotels in our queries). Populated for vacation rentals.

Prices come back in EUR by default (matches the flights tool's typical response currency for European-IP users). Pass currency (ISO 4217, e.g. "USD", "JPY", "GBP") to override per call. The currency field on each offer reflects what was actually requested.

Filter scoping (important β€” the wrong filter on the wrong category is silently dropped):

  • min_rating (1-5 stars) applies only to hotels. When category="all", it filters the hotel side; vacation rentals pass through unfiltered (they have no hotel class).

  • min_bedrooms and min_bathrooms apply only to vacation rentals. Filter the rental side; hotels pass through.

  • min_review_score, max_price_per_night, required_amenities, sort_by, max_results, currency apply uniformly.

address is always null on offers β€” SerpAPI's google_hotels list endpoint doesn't carry per-property addresses. Use latitude/longitude for location.

The review score is Google's native 0-5 scale (e.g., 4.6 / 5), NOT a 0-10 scale.

sort_by accepts: BEST (preserve SerpAPI's returned order; for the merged path this falls back to price-ascending as the tie-breaker since neither response has a globally meaningful rank), PRICE_LOW, PRICE_HIGH, RATING (star rating descending; hotels-only signal), REVIEW_SCORE (review_score descending, review_count tie-break).

PRE-CALL ELICITATION: Before calling this tool, confirm with the user:

  • Type of stay (category): default to "all" unless the user signals otherwise. "Find me a place to stay in Lisbon" stays at "all". "Find me a nice hotel in Lisbon" β†’ "hotels". "Find me a rental in Lisbon" β†’ "vacation_rentals". "Find me an Airbnb in Lisbon" β†’ "airbnb" (this hits Airbnb directly; SerpAPI doesn't include Airbnb listings).

  • Location: specific city or neighborhood β€” "Tampere" works, "Notting Hill, London" works, "somewhere in Europe" does not. Ask if vague.

  • Check-in and check-out dates: both required and check_out must be strictly after check_in. Confirm UTC-today or later.

  • Party size: adults, children, and number of rooms. Default is 2 adults / 0 children / 1 room β€” don't assume; ask if not stated.

  • Budget: any per-night ceiling? If the user said "cheap" or "affordable", ask for a concrete number to set max_price_per_night.

  • Must-have amenities: wifi, breakfast, parking, gym, pool, pet-friendly? Don't assume; ask.

  • Star rating or review score floor: "at least 4 stars", "well-reviewed (8+)"? Map to min_rating or min_review_score (remember review_score is 0-5, so "8+" should become min_review_score=4.0 or you should ask for clarification).

  • Rental size: if the user mentioned bedrooms or bathrooms ("a 2-bedroom apartment"), set min_bedrooms / min_bathrooms. These constrain the vacation-rental side only.

  • Sort priority: cheapest first, highest-rated, best location? Map to sort_by.

  • Currency: infer from the user's stated location or budget. "I'm in Tokyo, budget Β₯30000/night" β†’ currency="JPY", max_price_per_night=30000. "$200/night in NYC" β†’ currency="USD". Default "EUR" if the user gives no signal. Always pass the currency that matches the units the user spoke in for max_price_per_night β€” mixing currencies silently corrupts the budget filter.

RESULT PRESENTATION: When returning 2+ stays, render them as an interactive artifact with one card per offer. Each card shows:

  • The stay name, prominent and large at the top of the card (it carries the card's visual hierarchy in the absence of a photo).

  • A small category badge at the top: Hotel or Vacation rental, taken from the category field.

  • Star rating (hotels only β€” render as filled stars if you can) and review_score with review_count: "4.6 / 5 (686 reviews)".

  • For vacation rentals, surface bedrooms / bathrooms / sleeps inline if present (e.g. "2 BR Β· 2 BA Β· sleeps 6").

  • Price per night with the total alongside in smaller text, in the response currency.

  • For offers with a non-empty sources array, show "from €X on [cheapest source]" with a smaller "also on [other sources]" note when 2+ sources are present.

  • Top 3-4 amenities pulled from the amenities list.

  • Short description if present (hotels only β€” rentals leave this null and surface essential_info via the bedrooms/bathrooms/sleeps fields above).

  • A "Book on Google Hotels" button linking to booking_url, opening in a new tab.

Do NOT render the images field as photo elements. Hotel image CDNs (Google's signed gps-cs-s URLs, hotelbeds, trvl-media, bstatic, giata) use hotlink protection that breaks these URLs outside their intended hosts; broken images degrade the card more than missing photos. The images field stays on the response model for future use (e.g., a server-side image proxy layer), but card rendering should be text-only. Compensate for the missing visual hierarchy by making the stay name larger and prominent at the top of each card.

If the response has a non-empty warnings array, surface them verbatim above the cards (e.g., "Note: vacation rental data was unavailable for this query; showing hotels only."). Do NOT silently swallow them.

Sort cards by the same sort_by the user requested. For a single result, prose is fine.

get_stay_detailsA

🎯 RENDERING DIRECTIVE β€” READ FIRST. Render the result as a single rich HTML/React artifact card. The booking_partners array is the headline payload β€” surface one prominent "Book on [partner]" button per partner, side-by-side in a row, styled as HTML buttons (NOT inline markdown links). Show price per partner on the button or directly under it. The user is drilling into ONE property to book; the card should make the booking-partner choice feel like a real product page, not a wall of text.

Fetch rich per-property details for a single stay (hotel or vacation rental) the user has already seen in a search_stays result.

Takes a property_token (copied from any offer in a search_stays response) plus the same check_in/check_out dates and party size used for the original search. Returns a single StayDetails object β€” NOT a list.

USE THIS TOOL WHEN: the user has narrowed down to a specific property from a previous search_stays result and wants more detail before booking β€” typical phrasings: "tell me more about [hotel name]", "what's it like inside", "show me the booking options", "what's near it", "is breakfast included".

DO NOT USE THIS TOOL WHEN: the user is still browsing or hasn't specified a property. Use search_stays first.

Returns:

  • description: long-form prose (rentals: usually 1–2 paragraphs; hotels: 1–3 sentences).

  • booking_partners: list of OTAs offering this property with link (direct deep-link to the partner's booking flow), price_per_night, total_price, official (true if the property's own site), free_cancellation. This is the key payload β€” surface these as prominent "Book on X" buttons.

  • nearby_places: up to ~14 entries (airports, transit stations, restaurants, landmarks) each with name, category, latitude, longitude. Use to answer "what's nearby" questions.

  • amenities / excluded_amenities: the full lists (no top-3 truncation).

  • check_in_time / check_out_time: e.g. "3:00 PM" / "11:00 AM".

  • star_rating, review_score (0–5), review_count, location_rating.

address is NOT in the response. SerpAPI's property_details endpoint doesn't carry a postal address. Use the GPS coordinates + nearby_places to communicate location.

Costs 1 SerpAPI quota call per invocation. Cached aggressively (TTL ~5 min by default) β€” repeat calls for the same (token, dates) tuple are free.

RESULT PRESENTATION: Render as a single rich card with the booking_partners list prominently displayed (one button per partner, "Book on [name] β€” €X/night, free cancellation: yes/no"). If the user asked about a specific aspect (location, breakfast, refundability), lead with that. Surface the GPS coordinates on a small map link if you have that capability.

search_activitiesA

🎯 RENDERING DIRECTIVE β€” READ FIRST. When this tool returns 2+ activities, you MUST present them as an interactive HTML/React artifact (Artifacts block, not flowing prose). Each activity is a visually distinct CARD with a prominent "Find on Tripadvisor" button styled as an HTML button, NOT an inline markdown link. Include the activity-type badge (Sight / Experience) prominently. If the call is part of a larger trip plan, the plan itself should be an artifact containing the activity cards. Single-result responses may use prose.

Search Tripadvisor's "Things to Do" (sights + bookable experiences/tours) for a location, optionally filtered by free-text query, place type, and minimum rating.

DISTINCT FROM search_events: activities are ongoing (visit a museum, take a cooking class anytime); events are date-specific (a concert on June 21). Use this for "what should I do in X"; use search_events for "what's happening while I'm there".

USE THIS TOOL WHEN:

  • The user asks "what should I do in X" / "things to do in X" / "tours in X"

  • They name an activity type ("cooking classes", "boat tours", "museums", "wine tasting")

  • They want recommendations based on their preferences

Inputs:

  • location (string, required) β€” free-text city or neighborhood. Combined with query into a single Tripadvisor search.

  • query (string, optional) β€” free-text filter on activity type. Natural language works: "cooking class", "boat tours", "wine tasting", "free walking tour".

  • place_type_filter (enum, optional, default "both") β€” one of "sights" (free attractions like museums, viewpoints), "experiences" (bookable tours), or "both" (default).

  • min_rating (float, optional) β€” minimum review score 0.0-5.0. Results without a rating are excluded when this is set.

  • max_results (int, optional, default 15) β€” 1-50.

Returns ActivityOffer entries each with:

  • offer_id β€” Tripadvisor's place_id, stable per activity. Use this to drill in via get_activity_details (when implemented).

  • name β€” activity name.

  • activity_type β€” "sight" (free, non-bookable) or "experience" (bookable tour).

  • rating, review_count β€” 0-5 scale (Tripadvisor's native).

  • description β€” short prose (often missing on generic city searches; usually present on specific-activity searches).

  • location β€” text "City, Country".

  • thumbnail β€” URL (NOT hotlink-safe β€” don't render as a photo element).

  • highlighted_review β€” {text, mention_count} β€” a relevant review snippet.

  • booking_url β€” Tripadvisor listing URL. For experiences, this is the path to Viator tickets; for sights, it's the info page.

No coordinates and no price. Tripadvisor's search endpoint surfaces neither. Use get_activity_details(offer_id) (when implemented) to get price + duration + a direct Viator URL for bookable experiences.

PRE-CALL ELICITATION β€” three branches:

Branch 1: User names a specific activity type. "Find cooking classes in Lisbon." β†’ query="cooking class". Search immediately.

Branch 2: User asks for a recommendation. "What should I do in Lisbon?" β€” before searching, infer the user's interests from conversation context + your own memory of them ("they love food and wine", "they're into history"). Bake the interest into query. NOTE: The MCP tool does NOT read Claude's memory β€” you (Claude) do the inference and pass the resulting query string. If memory yields nothing actionable, fall to Branch 3.

Branch 3: User is vague and you have no preference signal. "Things to do in Lisbon?" with empty conversation context. Ask ONE clarifying question: "Any particular interest β€” food, history, outdoors, nightlife?" Then search.

RESULT PRESENTATION:

  • Card-based artifact, one card per result.

  • For Branch 2 (memory-driven), preamble: "Based on your interest in food and wine, here are top-rated experiences in Lisbon." β€” makes the inference legible.

  • Card content: name, activity_type badge (Sight / Experience), rating + review_count, location, the highlighted_review.text as a 1-line testimonial, "Find on Tripadvisor" button β†’ booking_url.

  • Do NOT render thumbnail as a photo element (Tripadvisor's CDN hotlink-protects). Same no-photos rule as stays/events.

  • For a single result, prose is fine.

search_eventsA

🎯 RENDERING DIRECTIVE β€” READ FIRST. When this tool returns 2+ events, you MUST present them as an interactive HTML/React artifact (Artifacts block, not flowing prose). Each event is a visually distinct CARD with one "Tickets on [vendor]" button per ticket_sources entry (or a single button on ticket_url if no extras), styled as HTML buttons, NOT inline markdown links. If the call is part of a larger trip plan, the plan itself should be an artifact containing event cards. Single-result responses may use prose.

Search Google for time-bound events β€” concerts, festivals, sports games, comedy shows, conferences β€” happening at a location, optionally filtered by event type and date range.

DISTINCT FROM search_activities: events are time-bound (a specific date or window); activities (tours, attractions) are ongoing. Use this tool for "what's on while I'm there"; use search_activities for "what should I do".

USE THIS TOOL WHEN:

  • The user asks "what's happening in X" / "events in X" / "any concerts in X" / "is BTS playing anywhere I'm going"

  • They mention a specific event type ("concerts", "festivals", "sports", "comedy", "theatre")

  • They're planning a trip and want time-bound options to anchor the dates around

Inputs:

  • location (string, required) β€” free-text city. Combined with query into the SerpAPI search string.

  • query (string, optional) β€” event-type filter. Examples: "concerts", "festivals", "sports", "comedy", "theatre", or a specific artist/team ("BTS", "Coldplay").

  • date_filter (enum, optional) β€” one of "today", "tomorrow", "week", "weekend", "next_week", "month", "next_month". SerpAPI's named-range filter; do NOT pass arbitrary date strings. If the user wants a specific calendar month, bake the month name into query instead (e.g. query="concerts June 2026").

  • max_results (int, optional, default 15) β€” 1-50.

Returns up to max_results EventOffer entries, each with:

  • offer_id β€” stable hash for downstream reference

  • title β€” event name

  • start_date_raw β€” SerpAPI's "Jun 21" style string (month + day, no year β€” when_text carries the year)

  • when_text β€” full formatted display string: "Fri, Jul 17, 8 – 11 PM GMT+2"

  • venue_name, venue_rating, venue_review_count β€” venue info if available

  • address β€” flattened single string ("B.Leza Club, Cais do GΓ‘s 1, Lisbon, Portugal")

  • description β€” short text from Google

  • thumbnail, image β€” URLs (NOT hotlink-safe β€” same rule as stays, don't render as photo elements)

  • ticket_url β€” primary deep-link to the ticket vendor (Viagogo, Eventbrite, Spotify Concerts, venue site β€” varies per event)

  • ticket_sources β€” list of additional ticket vendors with {source, link} per entry. Surface all of these as "Tickets on X" buttons so the user can comparison-shop.

PRE-CALL ELICITATION:

  • If the user names an event type, set query. "Concerts in Lisbon" β†’ query="concerts".

  • If they mention a relative date ("this weekend", "next week", "this month"), set date_filter to the matching enum.

  • If they mention a specific calendar month + year, bake it INTO the query string ("concerts June 2026") instead of using date_filter.

  • If they're vague ("things happening in Lisbon"), call with no query and no date_filter β€” default upcoming events.

RESULT PRESENTATION: card-based artifact, one card per event. Lead with title + when_text + venue_name. Show "Tickets on [source]" buttons (one per ticket_sources entry); for events with no ticket_sources, surface the primary ticket_url as a single button. Do NOT render thumbnail/image as photo elements (same hotlink-protection issue as stays). For a single result, prose is fine.

convert_currencyA

Convert a numeric amount between two ISO 4217 currencies using the European Central Bank's daily reference rates.

USE THIS TOOL WHEN:

  • The user asks for a conversion ("how much is Β₯30,000 in euros?", "what's $200 in pounds?")

  • You're presenting mixed-currency trip totals (flights in EUR + hotel in USD + activity in GBP) and want to give one consolidated number

  • The user wants to compare prices across vendors quoting in different currencies

Inputs:

  • amount (float, > 0) β€” the numeric value to convert.

  • from_currency (3-letter ISO 4217 code, uppercase) β€” e.g. "EUR", "USD", "JPY".

  • to_currency (3-letter ISO 4217 code, uppercase) β€” e.g. "EUR", "USD", "GBP".

Returns:

  • converted_amount β€” the result, rounded to 2 decimal places in your response (the raw float is precise).

  • rate β€” the effective rate (1 from_currency = rate to_currency).

  • rate_date β€” the ISO date of ECB's published rates. ECB updates daily around 16:00 CET. Weekend / holiday queries return the previous business day's rates β€” disclose this if the gap is more than 3 days.

  • source β€” always "ECB".

Powered by the European Central Bank's daily reference rates feed (free, no API key). 29+ currencies covered (USD, EUR, JPY, GBP, CAD, AUD, CHF, SEK, NOK, DKK, INR, MXN, BRL, SGD, KRW, CNY, THB, HKD, NZD, CZK, HUF, IDR, ILS, ISK, MYR, PHP, PLN, RON, TRY, ZAR). If the user names a currency we don't recognize, we return invalid_input.

RESULT PRESENTATION: inline prose, not an artifact. Example: "Β₯30,000 = €182.45 (rate as of 13 May 2026 via ECB)." For a multi-line trip-cost summary, include the rate_date once at the bottom rather than per-line.

get_weather_forecastA

🎯 RENDERING DIRECTIVE β€” READ FIRST. When this tool returns 3+ forecast days, render them as an HTML/React artifact β€” a horizontal day-strip or 7-day card grid with one tile per day (day name + emoji icon + high/low + precip%), NOT a paragraph or table-in-prose. 1-2 days may be prose. If used as context inside a trip plan, embed the strip inside the plan's artifact.

Get a 7-day weather forecast for a city or specific coordinates. Powered by Open-Meteo (free, global, no API key required).

USE THIS TOOL WHEN:

  • The user is planning a trip and packing or scheduling decisions hinge on weather ("will it rain in Lisbon next week", "what's the weather like in Tokyo for the second week of March")

  • The user is comparing dates and wants to bias toward sunnier ones

  • You're already showing flight or stay options and want to enrich them with a weather context line ("FYI, expect rain Thursday β€” bias indoor activities")

Inputs:

  • location (string) β€” free-text city or neighborhood. Resolved to coordinates via OpenStreetMap Nominatim. Examples: "Tampere, Finland", "Notting Hill, London".

  • OR latitude + longitude (floats) β€” direct coordinates, skip the geocoding step.

  • start_date (YYYY-MM-DD) β€” optional. Defaults to today (UTC).

  • end_date (YYYY-MM-DD) β€” optional. Defaults to start_date + 6 days. Hard cap: forecast horizon is 7 days from today.

  • units β€” "metric" (default, Β°C, km/h) or "imperial" (Β°F, mph).

Returns a GetWeatherForecastResult with:

  • location β€” echoed/resolved label

  • latitude, longitude, timezone β€” the resolved coordinates and IANA timezone

  • units β€” "metric" or "imperial"

  • days[] β€” list of WeatherDay (date, high_temp, low_temp, temp_unit, condition_summary, weather_code, precipitation_probability_percent, sunrise, sunset)

PRE-CALL ELICITATION:

  • For "weather in X" with no date hint, default to a 7-day forecast starting today.

  • For a specific date ("weather in Tokyo on Friday"), set both start_date and end_date to that date.

  • For a range ("weather in Lisbon next week"), infer the Mondayβ†’Sunday range from "next week".

  • If the user gives only a country ("weather in Italy"), ask for a specific city.

RESULT PRESENTATION:

  • For 4+ days, render as a small artifact: one row per day with date, high/low (with unit symbol), condition + a small WMO-driven emoji (β˜€οΈ partly cloudy, 🌧️ rain, β›ˆοΈ thunderstorm, ❄️ snow, ☁️ overcast), precip%.

  • For 1-3 days, prose is fine.

  • Always disclose units once at the top ("All temperatures in Β°C.").

  • If trip planning is in flight, lead with the rainy days the user should plan around.

watch_flight_priceA

Register a persistent watch on a specific flight route, departure date, and price threshold. When the user later asks "any deals?", list_active_watches re-runs the search and reports whether the latest price has dropped to or below the threshold.

USE THIS TOOL WHEN: the user says something like "watch this route", "tell me if the price drops below X", "alert me if Y becomes cheaper", "monitor flights from A to B around date Z".

DO NOT USE THIS TOOL FOR ONE-OFF SEARCHES β€” use search_flights for those.

Inputs are the same shape as search_flights (origin, destination, departure_date, optional return_date, etc.) plus:

  • threshold_price: numeric ceiling in the currency you also pass. The watch "fires" (status='alerted') when a refresh observes price ≀ threshold.

  • currency: ISO 4217 currency code (e.g. "EUR", "USD"). Must match the units of threshold_price.

  • note: optional free-text reminder ("for parents' anniversary", "cap to budget for Q3").

Returns the new watch's watch_id (a 12-character hex string). Hand it back to the user so they can cancel later with cancel_watch(watch_id).

The watch persists across restarts (it's in SQLite under ~/.trip-search-mcp/watches.db). Closing Claude Desktop doesn't lose your watches.

PRE-CALL ELICITATION:

  • Confirm the route and dates the user wants to watch.

  • Confirm the threshold price AND its currency explicitly β€” mixing currencies silently breaks the alert logic. Example: "I want to fly to Tokyo if it drops below 800 EUR" β†’ threshold_price=800, currency="EUR".

  • If the user said "any time" or "flexible dates", offer to use search_cheapest_dates first to pick a candidate date, then watch THAT specific date.

The watch makes ONE fli call when refreshed (per active watch). Refresh frequency is controlled by list_active_watches.refresh_after_hours (default 6h).

list_active_watchesA

🎯 RENDERING DIRECTIVE β€” READ FIRST. When 2+ watches come back, render them as an HTML/React artifact β€” one card per watch with a clear "Cancel" button (callable via cancel_watch(watch_id)) and, for alerted watches, a "Book now" button to the flight booking URL. Alerted watches must be visually flagged (e.g. green badge or 🎯 callout). 1 watch may be prose.

List the user's active flight price watches. Re-runs any watch whose latest check is older than refresh_after_hours (default 6h) and flips status to "alerted" when the latest price is at or below the watch's threshold.

USE THIS TOOL WHEN: the user asks "any deals?", "what's the price of [route] looking like?", "show my watches", "anything trigger yet?", "did the Lisbon trip get cheaper?". Also use it proactively at the start of a session if you know the user has watches set up.

Returns a list of watch objects, each with:

  • watch_id, route (formatted "ORIGIN β†’ DESTINATION"), departure_date, return_date

  • threshold_price, currency

  • status: "active" (no alert) or "alerted" (price hit threshold during refresh)

  • last_price / last_currency / last_offer_id: the latest observed price

  • last_checked_at: timestamp of the latest refresh

  • alerted_at: when the alert fired (null if not alerted)

  • note: the user's optional note from creation time

  • gap: numeric last_price - threshold_price (negative = below threshold, positive = above). Use this to summarize "X EUR below your target" or "still Y EUR above target".

Each refresh costs ONE fli call. Refresh frequency is bounded by refresh_after_hours β€” repeated calls within the cutoff window are free (no fli traffic). If you want a forced refresh, pass refresh_after_hours=0.

RESULT PRESENTATION: If any watch is alerted, lead with it (a small "🎯 Deal!" callout works well). For non-alerted watches, show the current gap ("currently 53 EUR above target, last checked 2h ago"). For never-checked watches, say so.

If include_cancelled=true, also include watches the user cancelled β€” useful when they ask "show me everything" or "what did I cancel last week?".

cancel_watchA

Cancel a previously created flight price watch by its watch_id. Use when the user says "stop watching that route", "cancel the Lisbon watch", "I already booked, take it off the list".

The watch is marked cancelled (not deleted), so it can still appear in list_active_watches(include_cancelled=true) if the user asks "what did I cancel?".

Returns {"watch_id": ..., "status": "cancelled"} on success.

If the user knows the route but not the watch_id, call list_active_watches first to find it, then pass the matching watch_id here.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nanwer/trip-search-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server