trip-search-mcp
Allows searching vacation rentals on Airbnb.
Allows searching flights and hotels via Google Flights and Google Hotels.
Allows searching activities on Tripadvisor.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@trip-search-mcpFind me cheap flights from New York to London next week."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
trip-search-mcp
Let Claude plan trips for you, in plain English. Live searches against Google Flights, Google Hotels, vacation rentals, Airbnb, Tripadvisor activities, and event ticket vendors ā plus weather forecasts, currency conversion, persistent price watches, and per-property detail drill-downs. Eleven tools, one config block.
You: Find me round-trip flights Helsinki ā Washington DC for May 18,
returning May 29, one stop or fewer.
Claude: [calls search_flights with WAS auto-expanded to IAD, DCA, BWI;
merges 3 parallel results, ranks cheapest first, returns a
summary with "Book on Google Flights" links]š FEATURES.md has the full plain-English feature list with paste-ready example prompts for every capability ā read that to see what's possible.
š TRIP-PLANNING-EXPANSION-SPEC.md tracks the five-track expansion plan (weather, currency, events, activities, drill-down). Weather is shipped; the other four are queued.
Before you start
You need:
A computer running macOS, Windows, or Linux
Claude Desktop, signed in
About 5 minutes the first time
You do NOT need an account anywhere except Claude ā unless you also want hotel search, which uses a free SerpAPI key (covered as an optional step below).
Related MCP server: MCP Travel Concierge Server
Install ā step by step
Everything below happens in your Terminal app (macOS/Linux) or PowerShell (Windows).
Don't know what a terminal is? macOS: press
ā+Space, typeTerminal, press Enter. Windows: press the Win key, typePowerShell, press Enter.
1. Install Python 3.12 (skip if you already have it)
python3 --versionIf you see Python 3.12.x or higher, jump to step 2. Otherwise install uv ā one line, brings Python with it:
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh# Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"Open a fresh terminal window after the installer finishes so the uv command is on your path.
2. Download the project
git clone https://github.com/nanwer/trip-search-mcp.git
cd trip-search-mcpMissing git? macOS: run xcode-select --install. Windows: install from git-scm.com and reopen PowerShell.
3. Install the package
uv venv
uv pip install -e .Creates .venv/ and installs everything. About 30 seconds.
4. Find the absolute path to the venv Python
You'll paste this into Claude Desktop's config in the next step.
# macOS / Linux
echo "$(pwd)/.venv/bin/python"# Windows
echo "$(Resolve-Path .\.venv\Scripts\python.exe)"Copy what it prints ā looks like /Users/you/trip-search-mcp/.venv/bin/python (macOS) or C:\Users\you\trip-search-mcp\.venv\Scripts\python.exe (Windows).
5. Add a trip-search entry to Claude Desktop's config
This is the one step where you have to edit a text file by hand (or get Claude to edit it for you ā see the callout below). The file is JSON; if you've never edited JSON before, just be careful with commas and quotes.
Where is the file?
OS | Path | Quickest way to find it |
macOS |
| In Finder, hit |
Windows |
| In File Explorer, paste |
Linux |
| Open in your favorite text editor. |
Open the config file:
# macOS
open -e "$HOME/Library/Application Support/Claude/claude_desktop_config.json"# Windows
notepad "$env:APPDATA\Claude\claude_desktop_config.json"5a. Pick your scenario
The config file is shared across every MCP server Claude Desktop knows about. Read the right scenario below before editing ā adding trip-search to a file that already has other servers in it is different from setting it up from scratch.
š Not sure which scenario you're in or worried about breaking things? Take a screenshot of your current config file (or copy-paste its contents) into a Claude chat and ask: "Merge a trip-search block into this MCP config without removing my existing servers. My venv Python path is /PASTE/PATH/FROM/STEP-4/HERE." Claude will hand back the full merged JSON. Paste that back into the file. No JSON wrangling required.
Scenario A ā You've never set up an MCP server before (fresh file)
The file probably doesn't exist yet. Create it:
# macOS
mkdir -p "$HOME/Library/Application Support/Claude"
cat > "$HOME/Library/Application Support/Claude/claude_desktop_config.json" << 'JSON'
{
"mcpServers": {
"trip-search": {
"command": "/PASTE/PATH/FROM/STEP-4/HERE",
"args": ["-m", "trip_search_mcp.server"]
}
}
}
JSON# Windows
New-Item -ItemType Directory -Path "$env:APPDATA\Claude" -Force | Out-Null
@'
{
"mcpServers": {
"trip-search": {
"command": "C:\\PASTE\\PATH\\FROM\\STEP-4\\python.exe",
"args": ["-m", "trip_search_mcp.server"]
}
}
}
'@ | Out-File -Encoding utf8 "$env:APPDATA\Claude\claude_desktop_config.json"Then open it in a text editor and replace /PASTE/PATH/FROM/STEP-4/HERE with the path you copied in step 4. Windows users: every \ in the path must be doubled to \\.
Scenario B ā You already have other MCP servers configured
Your file looks something like this (the names will differ ā yours might have Outline, Slack, Figma, etc.):
{
"mcpServers": {
"outline": {
"command": "...",
"args": [...],
"env": {...}
}
}
}You need to add the trip-search block alongside your existing one(s). Open the file:
# macOS
open -e "$HOME/Library/Application Support/Claude/claude_desktop_config.json"# Windows
notepad "$env:APPDATA\Claude\claude_desktop_config.json"Then add "trip-search": { ... } inside mcpServers. The result should look like this:
{
"mcpServers": {
"outline": {
"command": "...",
"args": [...],
"env": {...}
},
"trip-search": {
"command": "/PASTE/PATH/FROM/STEP-4/HERE",
"args": ["-m", "trip_search_mcp.server"]
}
}
}ā ļø Two things to watch out for:
Don't forget the comma after the closing
}of your existing server block, before"trip-search":. Without it, the file is invalid JSON and Claude Desktop will load no MCP servers.Windows paths: every
\in thecommandfield must be doubled (\\). Example:"command": "C:\\Users\\you\\trip-search-mcp\\.venv\\Scripts\\python.exe"
Save the file when done.
Lost the formatting? Paste your file's current contents (and the path from step 4) into a Claude chat and ask it to add the trip-search block for you. Way safer than hand-editing if you're not comfortable with JSON.
6. Fully quit and reopen Claude Desktop
Closing the window isn't enough. Quit from the menu bar (macOS: āQ or right-click the dock icon ā Quit) or from the system tray (Windows: right-click the Claude icon ā Quit). Then reopen.
7. Test it
Open a new chat in Claude Desktop. Click the hammer/tools icon at the bottom of the message box ā you should see trip-search with 7 always-on tools plus 4 more after step 8 below:
Tool | Needs SERPAPI_KEY? |
| No |
| No |
| No |
| No |
| No |
| No |
| Yes |
| Yes |
| Yes |
| Yes |
Ask Claude:
"Find me round-trip flights from JFK to LHR, leaving July 12 returning July 22, 1 adult, economy."
If you get a summary with prices and a "Book on Google Flights" link, you're done. Browse FEATURES.md for everything else you can ask.
Step 8 (optional) ā turn on hotel + event + activity search
Hotels, vacation rentals, events, activities, and get_stay_details use SerpAPI ā free tier 100 searches/month. The flight tools, the Airbnb category, weather, currency, and watches all work without it.
Sign up at serpapi.com (Google login works).
Copy your key from serpapi.com/manage-api-key.
Open your config file again and add an
envblock to the trip-search entry. Two scenarios:If trip-search is your only MCP server, your file becomes:
{ "mcpServers": { "trip-search": { "command": "/PASTE/PATH/FROM/STEP-4/HERE", "args": ["-m", "trip_search_mcp.server"], "env": { "SERPAPI_KEY": "paste-your-key-here" } } } }If you have other MCP servers alongside trip-search, only modify the trip-search block ā leave the others untouched:
{ "mcpServers": { "outline": { ... }, // leave alone "slack": { ... }, // leave alone "trip-search": { "command": "/PASTE/PATH/FROM/STEP-4/HERE", "args": ["-m", "trip_search_mcp.server"], "env": { // ā add this block "SERPAPI_KEY": "paste-your-key-here" } } } }ā ļø Don't forget the comma after
"args": [...]before"env":ā without it, the JSON is invalid.āQ and reopen Claude Desktop. The four SerpAPI-gated tools (
search_stayshotels mode,get_stay_details,search_events,search_activities) now work.
š Again, if you'd rather not hand-edit JSON, paste your current config plus the API key into a Claude chat and ask it to add the SerpAPI env block for you. Faster than chasing missing commas.
If something doesn't work
Symptom | Fix |
The | You forgot to fully quit. āQ (or quit from the system tray on Windows), then reopen. |
| The |
Claude says "the tool call timed out" | A previous Claude Desktop quit may have left a stale MCP subprocess running. Run |
| The |
Airbnb search returns an | Airbnb sometimes pushes back on scraping during high traffic. Wait a few minutes and retry. If it keeps failing, pyairbnb may need a release. |
docs/SETUP.md has a longer, verbose walkthrough.
Card / button rendering ā baked into the server
The MCP server publishes server-level instructions at handshake time that tell Claude:
Render multi-result tool output as an HTML artifact with one card per result (not as prose).
Every booking partner gets its own button, side-by-side.
These instructions load once when Claude Desktop connects to the server and persist for the whole chat ā you don't have to remember to add anything to your prompts.
If you still see prose-with-markdown-links for a specific query (Claude has discretion), you can reinforce with:
"Render every multi-result tool output as an HTML/React artifact card with prominent buttons ā don't summarize as prose."
Or for a single combined trip-plan artifact:
"Put the final trip plan in a single HTML artifact. Each item is a card with a big rounded 'Book on X' button ā not a markdown link."
The directive lives in src/trip_search_mcp/server.py as _SERVER_INSTRUCTIONS. Edit it there if you want to tune the behavior for your own use.
Updating to the latest version
Claude Desktop spawns the MCP subprocess once at launch and keeps running it. Pulling new code doesn't reload the running process ā you have to āQ and reopen Claude Desktop after every update.
Recent install (within the last few weeks)
cd /path/to/trip-search-mcp
git pull
uv pip install -e . # reinstalls in case dependencies changedThen āQ Claude Desktop and reopen.
Verify:
.venv/bin/python -c "from trip_search_mcp.server import mcp; print(mcp.name)"
# ā trip-search-mcpUpdating from an older version (before the flights-mcp ā trip-search-mcp rename)
Older installs used the module name flights_mcp (now trip_search_mcp). If your Claude Desktop config still says -m flights_mcp.server, the server will fail to start with ModuleNotFoundError after the update. Three things to fix:
Pull and reinstall:
cd /path/to/trip-search-mcp # path is unchanged; GitHub redirects the old repo URL git pull uv pip install -e . # picks up new deps including pyairbnbEdit your Claude Desktop config. Open
~/Library/Application Support/Claude/claude_desktop_config.json(macOS) or%APPDATA%\Claude\claude_desktop_config.json(Windows) and update theargsarray:- "args": ["-m", "flights_mcp.server"] + "args": ["-m", "trip_search_mcp.server"]Optionally rename the JSON key from
"flights"to"trip-search"so the entry in Claude Desktop's tools menu matches the new docs.āQ Claude Desktop and reopen.
Common gotchas during an update
Symptom | Cause / Fix |
| Your config still points at the old module name. See "Updating from an older version" above. |
| New dependency added since your install. Run |
| You didn't fully quit. Closing the window doesn't kill the subprocess on macOS or Windows. Use āQ (macOS) or the system-tray Quit (Windows). |
Updates seem to apply but a specific tool times out | Two MCP subprocesses may be running (Claude Desktop occasionally fails to kill the old one). Check with |
The Claude Code CLI (not Desktop) doesn't see the updates |
|
For developers
.venv/bin/pytest -q # 350 tests, all fixture-driven, no live API callsSource layout:
src/trip_search_mcp/
āāā server.py FastMCP entry point ā registers 7 tools
āāā models.py Pydantic I/O models
āāā cache.py TTL response cache (tool-namespaced keys)
āāā cities.py City code ā airport list map (27 cities)
āāā errors.py ErrorCode enum, ToolError, envelope helpers
āāā logging_config.py JSON-line file logger
āāā tools/
ā āāā search_flights.py
ā āāā search_cheapest_dates.py
ā āāā search_stays.py
ā āāā get_stay_details.py
ā āāā watch_flight_price.py
ā āāā list_active_watches.py
ā āāā cancel_watch.py
āāā fli_backend/ flights ā via fli library, no auth
āāā serpapi_hotels_backend/ hotels + vacation rentals ā SerpAPI
āāā serpapi_events_backend/ concerts + festivals + sports ā SerpAPI google_events
āāā tripadvisor_backend/ things-to-do ā SerpAPI Tripadvisor (ssrc=A)
āāā airbnb_backend/ Airbnb direct ā pyairbnb + Nominatim geocoding
āāā open_meteo_backend/ weather forecasts ā Open-Meteo, no auth
āāā ecb_backend/ currency conversion ā ECB daily feed, no auth
āāā monitoring/ SQLite-backed price watches (lazy refresh)Capture fresh real-data fixtures (uses live APIs ā burns 1 call each):
.venv/bin/python scripts/verify_fli.py # flights
.venv/bin/python scripts/verify_serpapi_hotels.py # hotels
.venv/bin/python scripts/verify_vacation_rentals.py # rentals
.venv/bin/python scripts/verify_property_details.py # property detailsFurther docs:
FEATURES.md ā every capability, plain English, with example prompts and combined-workflow scenarios.
docs/SETUP.md ā verbose install + troubleshooting.
AGENTS.md ā notes for AI coding agents working on this repo (topology, gotchas, hallucination traps).
BACKLOG.md ā completed items + new follow-ups surfaced during the work.
License
MIT.
Available Tools
11 toolscancel_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.
| Name | Required | Description | Default |
|---|---|---|---|
| watch_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses behavior: watch is marked cancelled (not deleted), return format on success, and implication of being able to retrieve cancelled watches. This goes beyond minimal disclosure.
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?
All sentences are valuable, front-loaded with core action, then examples, return format, and additional guidance. No waste.
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 the simple tool with 1 param and no annotations, the description covers purpose, usage, behavior, parameter meaning, and return format comprehensively. Output schema is described in-line.
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 single parameter watch_id is explained beyond the schema: it is the ID from watch_flight_price or list_active_watches. Since schema coverage is 0%, the description compensates fully.
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 cancels a flight price watch by watch_id, with specific verb and resource. It distinguishes from siblings like watch_flight_price and list_active_watches.
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?
Provides explicit usage scenarios (e.g., 'stop watching that route'), tells when to use list_active_watches first, and clarifies that cancelled watches are not deleted and can be listed with include_cancelled=true.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | ||
| to_currency | Yes | ||
| from_currency | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully carries the burden. It discloses important behaviors: weekend/holiday rate staleness, daily ECB updates at 16:00 CET, 29+ currencies, error handling (invalid_input), and return field details. This exceeds basic expectations.
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?
Description is well-structured with clear sections (USE THIS TOOL WHEN, Inputs, Returns, Powered by, RESULT PRESENTATION). However, it is somewhat verbose; a few redundant phrases could be trimmed without losing clarity.
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 the tool has 3 params and no annotations, the description covers all essential aspects: inputs, outputs, behavior, source, limitations (weekend rates), and presentation guidelines. The presence of an output schema reduces the need for return value details, but the description still adds useful context.
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?
Input schema has 0% description coverage, so the description must compensate. It provides full semantics: amount is numeric >0, from_currency and to_currency are 3-letter ISO uppercase with examples. Also states error condition for unrecognized currencies.
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 it converts a numeric amount between two ISO 4217 currencies using ECB rates. The verb 'convert' is specific and resource is well-defined. No sibling tool performs conversion, so distinction is clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly lists three usage scenarios ('USE THIS TOOL WHEN') including direct conversion requests and mixed-currency totals. It does not provide negative guidance (when not to use) or alternatives, but given sibling tools are unrelated, this is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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 withlink(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 withname,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.
| Name | Required | Description | Default |
|---|---|---|---|
| adults | No | ||
| currency | No | EUR | |
| check_in_date | Yes | ||
| check_out_date | Yes | ||
| property_token | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It discloses: costs 1 SerpAPI quota call, caching with TTL ~5 min, that address is NOT in response, and returns a single object not a list. No contradictions with annotations (none exist).
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 relatively long but well-structured: starts with rendering directive, then purpose, usage guidelines, return fields, and caveats. Every sentence adds value, though the rendering directive could be considered separate guidance for the agent's response rather than tool behavior.
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 the complexity (5 params, extensive output schema with nested objects, caching, quota), the description covers all essential aspects: input parameters, output fields, usage boundaries, and behavioral notes. It also mentions what is NOT returned (address). Output schema exists but description adds context beyond it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but description explains that property_token is 'copied from any offer in a search_stays response' and that dates and adults should match the original search. It provides meaning beyond schema for key parameters, though it doesn't explicitly describe currency (default provided in 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 clearly states: 'Fetch rich per-property details for a single stay (hotel or vacation rental) the user has already seen in a search_stays result.' It uses specific verb (fetch) and resource (per-property details for a single stay), and distinguishes itself from sibling search_stays by specifying it is for a single property already selected.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use: 'USE THIS TOOL WHEN: the user has narrowed down to a specific property...', and when not to use: 'DO NOT USE THIS TOOL WHEN: the user is still browsing or hasn't specified a property. Use search_stays first.' It provides clear context and an explicit alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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 labellatitude,longitude,timezoneā the resolved coordinates and IANA timezoneunitsā"metric"or"imperial"days[]ā list ofWeatherDay(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_dateandend_dateto 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.
| Name | Required | Description | Default |
|---|---|---|---|
| units | No | metric | |
| end_date | No | ||
| latitude | No | ||
| location | No | ||
| longitude | No | ||
| start_date | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, but description fully carries burden: explains data source (Open-Meteo), no API key needed, geocoding via Nominatim, default date behavior, hard 7-day cap, output structure, and rendering rules. 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?
Description is very long (800+ words) with redundancy between rendering directive and result presentation. However, it uses clear sections and bullet points, so readability is okay but conciseness suffers.
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 the output schema exists, description still thoroughly explains return fields, rendering guidelines, and pre-call behavior. Covers all key aspects for correct tool invocation and result usage.
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, but description compensates by detailing each parameter (location, lat/lon, start/end dates, units) with defaults, examples, and constraints (e.g., hard cap). Adds significant meaning beyond schema structure.
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?
Clearly states it fetches a 7-day weather forecast for a city or coordinates. Distinct from siblings like search_activities, search_events. Includes specific verb and resource.
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 'USE THIS TOOL WHEN' section with three clear scenarios (trip planning, date comparison, enriching context). Also has 'PRE-CALL ELICITATION' with date handling defaults, providing strong guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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_datethreshold_price,currencystatus:"active"(no alert) or"alerted"(price hit threshold during refresh)last_price/last_currency/last_offer_id: the latest observed pricelast_checked_at: timestamp of the latest refreshalerted_at: when the alert fired (null if not alerted)note: the user's optional note from creation timegap: numericlast_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?".
| Name | Required | Description | Default |
|---|---|---|---|
| include_cancelled | No | ||
| refresh_after_hours | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully explains behavior: re-runs watches, flips status, costs one call per refresh, bounded by refresh_after_hours, forced refresh option. It also details return fields and side effects.
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 overly long with rendering directives and result presentation tips that could be separate. It is well-structured but not concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers all aspects: purpose, usage, parameters, behavior, return fields, and even rendering suggestions. It is complete given the lack of annotations and output schema.
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?
Despite 0% schema coverage, the description explains both parameters: include_cancelled for listing cancelled watches, and refresh_after_hours for refresh frequency, including the forced refresh usage.
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 lists active flight price watches, re-runs old checks, and flips status on threshold hits. It distinguishes itself from siblings like cancel_watch and watch_flight_price.
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 examples are given: user queries like 'any deals?' or 'show my watches', and proactive use at session start. It provides clear context for when to invoke.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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 withqueryinto 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'splace_id, stable per activity. Use this to drill in viaget_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.textas a 1-line testimonial, "Find on Tripadvisor" button ābooking_url.Do NOT render
thumbnailas a photo element (Tripadvisor's CDN hotlink-protects). Same no-photos rule as stays/events.For a single result, prose is fine.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | ||
| location | Yes | ||
| min_rating | No | ||
| max_results | No | ||
| place_type_filter | No | both |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses limitations (no coordinates/price), rendering directive, pre-call elicitation strategy, and return format details beyond the input schema, fully compensating for missing 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?
Well-structured with front-loaded rendering directive, sections for usage, inputs, returns, and presentation. Every sentence adds value; no fluff.
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?
Completely covers rendering, parameter details, return field descriptions, limitations, and pre-call behavior, making it self-sufficient for correct invocation.
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?
Despite 0% schema coverage, each parameter is explained with context and examples (e.g., query accepts natural language, place_type_filter enum values, min_rating excludes unrated results).
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?
Clearly states it searches Tripadvisor's 'Things to Do' with specific verb 'Search' and distinguishes from sibling tool `search_events` by contrasting ongoing activities vs date-specific events.
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 lists when to use ('what should I do in X', 'things to do in X', etc.) and when not to (use search_events for date-specific events), plus three detailed pre-call branches.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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 ofANY(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_durationinteger.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_durationvalues; 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.
| Name | Required | Description | Default |
|---|---|---|---|
| origin | Yes | ||
| airlines | No | ||
| end_date | Yes | ||
| max_stops | No | ANY | |
| passengers | No | ||
| start_date | Yes | ||
| cabin_class | No | ECONOMY | |
| destination | Yes | ||
| is_round_trip | No | ||
| trip_duration | No | ||
| departure_window | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses result format (sorted list of date combinations and price), what is not returned (flight details), parameter semantics (e.g., departure_window exclusivity, airline filter behavior), currency behavior, and performance implications. It does not explicitly state the tool is read-only, but the context implies it, and the level of detail is high.
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 with section headers and bullet points, front-loading the purpose. However, it is somewhat verbose, particularly the rendering directive and pre-call elicitation sections, which could be condensed without losing essential guidance. Nonetheless, every part serves a clear purpose.
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 the tool's complexity (11 parameters, output schema present), the description is complete. It covers purpose, usage, parameter details, output format (list of entries with date and price), rendering guidance, and follow-up actions. The presence of an output schema reduces the burden, but the description still explains the output structure adequately.
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 input schema provides only types and defaults with 0% description coverage. The description compensates thoroughly by explaining every parameter's meaning, format, and behavior, including edge cases like trip_duration requirement for round trips, departure_window exclusivity, airlines filter semantics, and default values. This adds significant value beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Find which travel dates are cheapest across a flexible range' and distinguishes it from the sibling tool 'search_flights' by explicitly stating what it does not return and providing usage scenarios. The verb 'find' and resource 'cheapest travel dates' are specific and unambiguous.
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 includes explicit sections 'USE THIS TOOL WHEN' and 'USE search_flights INSTEAD WHEN' with typical user phrasings, and provides a 'PRE-CALL ELICITATION' section detailing required user inputs. This offers comprehensive guidance on when to invoke this tool versus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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 withqueryinto 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 intoqueryinstead (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 referencetitleā event namestart_date_rawā SerpAPI's"Jun 21"style string (month + day, no year āwhen_textcarries 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 availableaddressā flattened single string ("B.Leza Club, Cais do GĆ”s 1, Lisbon, Portugal")descriptionā short text from Googlethumbnail,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_filterto 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
queryand nodate_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.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | ||
| location | Yes | ||
| date_filter | No | ||
| max_results | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses the tool's behavior: data source (Google via SerpAPI), output structure (EventOffer fields), rendering constraints (artifact vs prose), image handling (hotlink warning), and pre-call logic. No contradictions and exceeds the burden for safe invocation.
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 with clear sections and a front-loaded rendering directive. However, it is quite verbose; some instructions could be condensed without losing clarity. Still, every sentence serves a purpose.
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 the tool's complexity and the presence of an output schema (described in text), the description is exceptionally complete: covers purpose, usage, parameters, output fields, rendering behavior, sibling differentiation, and pre-call elicitation. No obvious gaps remain for an 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?
Schema description coverage is 0%, but the description compensates fully: explains `location` as free-text, `query` with examples, `date_filter` with enum values and usage warnings, and `max_results` with default and range. Pre-call elicitation clarifies mapping from user requests to parameters.
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 with a specific verb ('Search Google for') and resource ('time-bound events'). It explicitly distinguishes from the sibling tool `search_activities` by contrasting time-bound events with ongoing activities, leaving no ambiguity.
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 includes a dedicated 'USE THIS TOOL WHEN' section with specific user query examples, and explicitly contrasts with `search_activities`. Pre-call elicitation rules further guide parameter selection, making usage conditions extremely clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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 ofANY(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 asdeparture_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 (setsinbound_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.
| Name | Required | Description | Default |
|---|---|---|---|
| adults | No | ||
| origin | Yes | ||
| infants | No | ||
| airlines | No | ||
| children | No | ||
| max_stops | No | ANY | |
| cabin_class | No | ECONOMY | |
| destination | Yes | ||
| max_results | No | ||
| return_date | No | ||
| departure_date | Yes | ||
| inbound_window | No | ||
| departure_window | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully carries the behavioral transparency burden. It discloses caching behavior (5-minute cache), date validation (rejects past dates), meaning of null fields (baggage_allowance, etc.), timezone handling (local times with IATA codes), city code expansion, and detailed filter semantics. No contradictions with annotations since none exist.
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 with clear sections but is overly long, including a rendering directive and pre-call elicitation that could be separated. While every sentence adds value, the length reduces conciseness. It front-loads the most important info but could be more succinct.
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 the tool's complexity (13 parameters, 3 required, output schema exists), the description covers all critical aspects: parameter semantics, behavioral nuances, error handling, caching, and result presentation. It is comprehensive and leaves no major gaps for an AI agent to misuse 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 must compensate. It explains critical parameters like origin/destination (IATA and city codes), max_stops (with exact meanings), departure_window and inbound_window (inclusive-start/exclusive-end semantics), and airlines filter behavior. However, it does not explain simpler parameters like adults, children, infants, cabin_class, and max_results, leaving some gaps.
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: 'Search live flight offers for a given route and date range using Google Flights data.' It uses a specific verb ('search') and resource ('flight offers'), and implicitly distinguishes from sibling tools like search_cheapest_dates and watch_flight_price by focusing on live searches for specific routes and dates.
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 extensive 'PRE-CALL ELICITATION' guidance on what user preferences to collect before calling, which indirectly informs when to use the tool. However, it does not explicitly contrast with sibling tools or state when not to use this tool, missing a direct exclusion statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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 ā usecategory="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_ratingis 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. Whencategory="all", it filters the hotel side; vacation rentals pass through unfiltered (they have no hotel class).min_bedroomsandmin_bathroomsapply only to vacation rentals. Filter the rental side; hotels pass through.min_review_score,max_price_per_night,required_amenities,sort_by,max_results,currencyapply 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 formax_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:
HotelorVacation rental, taken from thecategoryfield.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
sourcesarray, 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
amenitieslist.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.
| Name | Required | Description | Default |
|---|---|---|---|
| rooms | No | ||
| adults | No | ||
| sort_by | No | BEST | |
| category | No | all | |
| children | No | ||
| currency | No | EUR | |
| location | Yes | ||
| min_rating | No | ||
| max_results | No | ||
| min_bedrooms | No | ||
| check_in_date | Yes | ||
| min_bathrooms | No | ||
| check_out_date | Yes | ||
| min_review_score | No | ||
| required_amenities | No | ||
| max_price_per_night | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Since no annotations are provided, the description carries the full burden of disclosing behavioral traits. It extensively covers: use of SerpAPI with parallel calls for 'all' category (~3s latency, 2x quota cost), airbnb category being slower and more fragile, default currency (EUR), filter scoping (min_rating only hotels, etc.), address always null, review scale 0-5, sort_by options, rendering requirements (artifact with cards, no images due to hotlink protection), and warnings handling. No contradictions are present.
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 very long and verbose, containing extensive sections on pre-call elicitation and result presentation that could be abbreviated or separated. While well-organized (rendering directive first, then purpose, parameters, usage context), its length may overwhelm quick parsing. Not every sentence is essential; some repetition occurs (e.g., category descriptions appear in multiple places). Conciseness is moderately compromised.
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 the tool's complexity (16 parameters, 4 categories, filter scoping, rendering rules, output schema exists), the description is exceptionally complete. It covers input semantics, behavioral traits, output form, rendering directives, pre-call elicitation, and warning handling. The presence of an output schema reduces the need to describe return values. Sibling differentiation is clear.
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 has 0% description coverage, so the description must fully document parameters. It does so comprehensively: explains each category value, sort_by options, filter applicability (min_rating for hotels, min_bedrooms/min_bathrooms for rentals), currency override, and max_price_per_night. It also clarifies that 'address is always null', 'review_score is 0-5', and provides conversion guidance. All 16 parameters are effectively covered.
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 function: '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.' It explicitly distinguishes itself from siblings like search_flights and get_stay_details by specifying it searches for stays across hotels and vacation rentals, and it does not book reservations.
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 detailed guidance on when to use this tool, including a 'PRE-CALL ELICITATION' section that instructs the agent to confirm parameters like category, location, dates, etc., with the user. It differentiates between categories (all, hotels, vacation_rentals, airbnb) and specifies when each is appropriate. However, it does not explicitly mention that get_stay_details should be used for more details on a specific property, which would strengthen usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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 ofthreshold_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_datesfirst 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).
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | ||
| adults | No | ||
| origin | Yes | ||
| currency | No | EUR | |
| max_stops | No | ANY | |
| cabin_class | No | ECONOMY | |
| destination | Yes | ||
| return_date | No | ||
| departure_date | Yes | ||
| threshold_price | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, but the description fully covers behavioral traits: persistence across restarts via SQLite, refresh frequency controlled by list_active_watches, single API call per refresh, and alerting condition (price ⤠threshold).
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 relatively long but well-structured with clear sections (USE THIS, DO NOT USE, Inputs, Returns, PRE-CALL ELICITATION). It is front-loaded with the main purpose. Slightly verbose but still effective.
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 10 parameters, 4 required, and no schema descriptions, the description covers crucial aspects: watch behavior, parameter semantics for threshold and currency, return value (watch_id), persistence, and pre-call elicitation. Could elaborate on more parameters, but the reference to search_flights mitigates this.
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%, but the description explains key parameters: threshold_price, currency, and note. It states inputs are the same shape as search_flights for origin, destination, etc., though not all 10 parameters are individually described. The cross-reference is acceptable.
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 registers a persistent watch on a flight route, departure date, and price threshold. It distinguishes itself from sibling tools like search_flights (one-off) and list_active_watches (listing/refreshing).
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 provides when-to-use scenarios (e.g., 'watch this route') and when-not-to (one-off searches, redirecting to search_flights). Also suggests alternatives like search_cheapest_dates for flexible dates.
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.
11 tool updates
v0.2.0- First observed
cancel_watch - First observed
convert_currency - First observed
get_stay_details - First observed
get_weather_forecast - First observed
list_active_watches - First observed
search_activities - First observed
search_cheapest_dates - First observed
search_events - First observed
search_flights - First observed
search_stays - First observed
watch_flight_price
TDQS
Scored across 11 tools
Each tool targets a distinct domain or action: flight searching, price watching, stays, activities, events, weather, and currency conversion. There is no overlap between tools; even the flight-related tools (search_flights, search_cheapest_dates, watch_flight_price, list_active_watches, cancel_watch) have clearly differentiated purposes.
Tool names use a mix of verb styles: 'search_' for five tools, 'get_' for two, and individual verbs like 'cancel_', 'convert_', 'list_', and 'watch_'. While each name is clear, the lack of a uniform pattern makes the set slightly less predictable.
With 11 tools, the server covers essential trip planning needsāflight search, price monitoring, stay search, activities, events, weather, and currency conversionāwithout unnecessary bloat. The count is well-scoped for its domain.
The tool surface covers core trip planning tasks comprehensively. Minor gaps exist: get_activity_details is referenced but not implemented, and there is no tool for booking flights or stays (though that may be out of scope). Overall, agents can accomplish most planning workflows without dead ends.
Maintenance
Related MCP Connectors
Give AI assistants access to real-time data. Search the web, compare flights, find hotels, and more.
Travel tools for AI agents: plan and edit real trips, search stays and tours, import travel videos.
Plan trips directly into TravelOwl from a conversation with Claude.
Search award flights and cash fares, optimize points, and predict fares inside ChatGPT and Claude.
Related MCP Servers
- AlicenseAqualityFmaintenanceEnables LLMs to perform travel-related tasks by interacting with Google Maps and travel planning services including location search, place details, and travel time calculations.520 npm99MIT
- AlicenseNot gradedqualityFmaintenanceEnables comprehensive travel planning by integrating Google Travel Services and Amadeus GDS for dual flight and hotel searches, plus event discovery, weather forecasting, currency conversion, and location services. Combines consumer-friendly search with professional travel industry data for optimal trip planning.6MIT
- AlicenseAqualityBmaintenanceEnables travel search workflows including airport lookup, route comparison, travel timing guidance, and external booking links with commission-eligible links.559 npm1MIT
- AlicenseNot gradedqualityDmaintenanceEnables Claude to search and compare flights across multiple providers (Skyscanner, Google Flights, Kiwi.com) with smart caching, parallel queries, and flexible filtering.1MIT