Skill: adrianetti/travel-search (version 1.5.0)

--- name: travel-search description: "Find the best travel deals by searching and comparing flights, hotels, Airbnb stays, car rentals, and ferries across multiple providers simultaneously. Smart value scoring picks the optimal price-quality-convenience balance automatically. Plan complete trip itineraries with real prices and direct booking links. Use when: user asks about flights, travel, hotels, accommodation, Airbnb, apartments, villas, car rentals, ferry routes, trip planning, vacation planning, itinerary generation, finding cheap flights, best deals, comparing travel options, flexible dates, cheapest time to fly, price calendars, planning multi-city routes, or budget travel. Covers Kiwi.com (flights), Skiplagged (flights + hotels + cars), Trivago (hotels), Ferryhopper (ferries), optional Airbnb via local MCP, and Google Flights via fli. All primary providers are free with no API key required." metadata: { "openclaw": { "emoji": "✈️", "requires": { "bins": ["curl"] } } } --- # Travel Search Search flights, hotels, car rentals, and ferries across multiple free providers via MCP protocol. ## Quick Reference | Need | Provider | Reference | |------|----------|-----------| | Flights (creative routing) | Kiwi.com | [flights.md](references/flights.md) | | Flights + Hotels + Cars | Skiplagged | [skiplagged.md](references/skiplagged.md) | | Hotels (price comparison) | Trivago | [hotels.md](references/hotels.md) | | Ferries | Ferryhopper | [ferries.md](references/ferries.md) | | Flights (Google Flights) | fli | [google-flights.md](references/google-flights.md) | | Full trip itinerary | Multi-provider | [trip-planner.md](references/trip-planner.md) | | Best deal / price compare | Multi-provider | [price-tools.md](references/price-tools.md) | | Airbnb / apartment stays | Airbnb MCP | [airbnb.md](references/airbnb.md) | | Multi-city route optimizer | Multi-provider | [multi-city.md](references/multi-city.md) | | Destination intel (weather, visa, transport) | General knowledge + wttr.in | [travel-intel.md](references/travel-intel.md) | ## How It Works All providers use the MCP protocol (JSON-RPC 2.0 over HTTP). Call them with `curl`: ```bash # 1. Initialize session curl -s -X POST "$MCP_URL" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"openclaw","version":"1.0"}}}' # 2. Extract Mcp-Session-Id from response headers (if returned) # 3. Call a tool curl -s -X POST "$MCP_URL" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -H "Mcp-Session-Id: $SESSION_ID" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"TOOL_NAME","arguments":{...}}}' ``` Response format: SSE with `event: message` + `data: {JSON}`. Parse the `data` line. ## Decision Guide ### User wants flights, hotels, cars, ferries, or trip planning Read [price-tools.md](references/price-tools.md) for the **decision tree and comparison engine**. It covers: - Which providers to search and when - How to compare and score results across providers - How to present the single best recommendation + alternatives - Flexible dates, anywhere destinations, round-trip optimization For full trip itineraries, also read [trip-planner.md](references/trip-planner.md). It includes a **guided intake questionnaire** (7 quick questions in one message) for when users want help figuring out what they want. ### User wants to visit multiple cities Read [multi-city.md](references/multi-city.md) for route optimization. It finds the cheapest city order, allocates days, and handles open-jaw flights. ### Core principle **Always search multiple providers, score results, and present ONE best recommendation** with alternatives. The user should never have to compare — that's the agent's job. See [price-tools.md](references/price-tools.md) for the value scoring system. ## Presenting Results Use bullet lists (no markdown tables on Discord/WhatsApp). For each option show: - Route with stops (e.g., OVD → BCN → FCO) - Times and duration - Price - Booking link Group by: 💸 Cheapest → ⚡ Fastest → 🎯 Best value Always include booking deep links so the user can act immediately. ## Provider Endpoints ``` Kiwi: https://mcp.kiwi.com Skiplagged: https://mcp.skiplagged.com/mcp Trivago: https://mcp.trivago.com/mcp Ferryhopper: https://mcp.ferryhopper.com/mcp ``` ## Notes - All Tier 1 providers are free, no API key needed - Kiwi uses `dd/mm/yyyy` date format - Skiplagged uses `YYYY-MM-DD` date format - Always resolve city names to IATA codes first when using Skiplagged - Rate limit: be reasonable, don't spam requests - MCP sessions may expire; re-initialize if you get errors

path: README.md
content: # ✈️ travel-search

**The most complete free travel search skill for OpenClaw and AI agents.**

Search flights, hotels, car rentals, and ferries across multiple providers — all free, no API keys required. Real-time pricing with direct booking links.

[![ClawHub](https://img.shields.io/badge/ClawHub-travel--search-blue)](https://clawhub.ai/adrianetti/travel-search)

## Features

🛫 **Flights** — Search across Kiwi.com and Skiplagged with creative routing, hidden city fares, and flexible dates

🏨 **Hotels** — Compare prices across booking sites via Skiplagged and Trivago

🏠 **Airbnb** — Compare apartments and homes against hotels for the same stay (optional local MCP)

🚗 **Car Rentals** — Find the best deals via Skiplagged

⛴️ **Ferries** — Search 190+ operators across 33 countries via Ferryhopper

✈️ **Google Flights** — Widest airline coverage via `fli` (optional, local install)

## Why This Skill?

- **100% free** — No API keys, no registration, no paid tiers
- **Real-time data** — Live prices from actual providers, not cached or estimated
- **Direct booking links** — Every result includes a link to book immediately
- **Multi-provider** — Cross-reference prices across providers automatically
- **Modular** — Only loads what you need (flights, hotels, etc.)

## Install

```bash
openclaw skills install travel-search
```

Or clone directly:

```bash
git clone https://github.com/adrianetti/travel-search.git
cp -r travel-search ~/.openclaw/workspace/skills/
```

## Providers

| Provider | Type | Coverage | API Key |
|----------|------|----------|---------|
| [Kiwi.com](https://kiwi.com) | Flights | Worldwide, creative routing | 🆓 Free |
| [Skiplagged](https://skiplagged.com) | Flights + Hotels + Cars | Worldwide, hidden city fares | 🆓 Free |
| [Trivago](https://trivago.com) | Hotels | Worldwide, price comparison | 🆓 Free |
| [Airbnb MCP](https://github.com/borski/mcp-server-airbnb) | Apartments / homes | Short stays, groups, workcations | 🆓 Free (separate install required) |
| [Ferryhopper](https://ferryhopper.com) | Ferries | 33 countries, 190+ operators | 🆓 Free |
| [Google Flights](https://github.com/punitarani/fli) | Flights | Widest coverage | 🆓 Free (separate install required) |

All providers use the [MCP protocol](https://modelcontextprotocol.io/) (JSON-RPC 2.0 over HTTP) — no browser automation, no scraping.

## Usage Examples

Once installed, just ask your agent naturally:

- *"Find me cheap flights from Madrid to Tokyo in April"*
- *"Compare hotels in Rome for April 10-14"*
- *"What’s cheaper, Airbnb or hotel in Barcelona for 5 nights?"*
- *"Find the best apartment stay in Lisbon for a month"*
- *"What's the cheapest way to get from Oviedo to Rome?"*
- *"Find car rentals in Barcelona for next week"*
- *"Search ferries from Piraeus to Santorini in July"*
- *"Where can I fly cheap from Madrid?"* (uses Skiplagged's "anywhere" search)
- *"When is it cheapest to fly to London?"* (flexible date calendar)
- *"Plan me a 5-day trip to Rome with a budget of €800"* (full itinerary with prices)
- *"Build an itinerary for 2 weeks in Japan"* (day-by-day plan + flights + hotels)
- *"I want to visit Rome, Paris, and Amsterdam in 10 days — what's the best route?"*
- *"Eurotrip: 5 cities in 3 weeks, optimize for cheapest flights"*

## How It Works

The skill teaches AI agents to call travel provider MCP servers directly via `curl`. Each provider returns structured JSON with prices, routes, times, and booking links. The agent then formats and presents the best options.

```
User: "Find flights from Barcelona to Rome"
  → Agent loads references/flights.md
  → Calls Kiwi.com MCP API
  → Gets JSON with 15 flights, prices, deep links
  → Presents top 3-5 options grouped by cheapest/fastest/best value
```

## Skill Structure

```
travel-search/
├── SKILL.md                         # Core skill + decision guide
├── references/
│   ├── flights.md                   # Kiwi.com API docs
│   ├── skiplagged.md                # Skiplagged API docs  
│   ├── hotels.md                    # Trivago API docs
│   ├── airbnb.md                    # Airbnb MCP docs
│   ├── ferries.md                   # Ferryhopper API docs
│   └── google-flights.md            # fli / Google Flights docs
├── scripts/
│   └── mcp-call.sh                  # Helper script for MCP calls
└── ROADMAP.md                       # Upcoming features
```

## Roadmap

- **v1.1** ✅ — Trip Planner (full itinerary: flight + hotel + day-by-day + budget)
- **v1.2** ✅ — Smart Price & Value Engine (cross-provider comparison, value scoring, price calendars, deal detection)
- **v1.3** ✅ — Airbnb Integration (short-stay vs hotel comparison)
- **v1.4** ✅ — Multi-city Optimizer (cheapest route, day allocation, open-jaw, train alternatives)
- **v1.5** ✅ — Travel Intel (weather, visa, currency, transport, safety, connectivity)

See [ROADMAP.md](ROADMAP.md) for details.

## Contributing

PRs welcome! Especially for:
- New free travel provider integrations
- Improved API documentation
- Bug fixes and edge cases
- Translation of SKILL.md descriptions

## License

MIT


path: ROADMAP.md
content: # Roadmap — travel-search

## v1.0.0 ✅ (Released 2026-03-26)
- [x] Kiwi.com MCP — flights with creative routing
- [x] Skiplagged MCP — flights + hotels + car rentals
- [x] Trivago MCP — hotel price comparison
- [x] Ferryhopper MCP — ferries across 33 countries
- [x] Google Flights via fli (optional, requires local install)
- [x] Helper script (mcp-call.sh)
- [x] Published on ClawHub + GitHub

## v1.1.0 ✅ — Trip Planner
- [x] Full itinerary generation: flight + hotel + day-by-day plan
- [x] Budget breakdown: flight + hotel + estimated food + local transport
- [x] "Plan me 5 days in Rome for €800" → complete trip with real prices
- [x] Multi-provider combination (cheapest flight + best-value hotel)
- [x] Daily cost estimates by region (Europe, Asia, Latin America, etc.)
- [x] Day-by-day itinerary with morning/afternoon/evening activities
- [x] Add `references/trip-planner.md`

## v1.2.0 ✅ — Smart Price & Value Engine
- [x] Value scoring system: price × quality × convenience → single best recommendation
- [x] Cross-provider comparison engine (Kiwi + Skiplagged parallel search, deduplication, scoring)
- [x] Price calendar via [REDACTED_SECRET] and [REDACTED_SECRET]
- [x] "Anywhere" search for flexible destinations ([REDACTED_SECRET])
- [x] Hotel scoring: rating × price × location × amenities
- [x] Deal detection with benchmarks ("🔥 40% below average!")
- [x] Complete decision tree: what to search when
- [x] Trade-off explanations for every alternative
- [x] Hidden cost flagging (baggage, breakfast, insurance)
- [x] Add `references/price-tools.md`

## v1.3.0 ✅ — Airbnb Integration
- [x] Integrate Airbnb MCP docs (`@openbnb/mcp-server-airbnb` via local `npx`)
- [x] Short-stay vs hotel automatic comparison workflow
- [x] Defaults for when Airbnb wins vs hotels by trip type
- [x] Airbnb value scoring (space, amenities, privacy, policies)
- [x] "What's cheaper, Airbnb or hotel in Barcelona for 5 nights?"
- [x] Add `references/airbnb.md`

## v1.4.0 ✅ — Multi-city Optimizer
- [x] Route optimization: "Visit Rome, Paris, Amsterdam in 10 days"
- [x] Price matrix builder for inter-city flights
- [x] Geographic flow optimization (minimize backtracking)
- [x] Smart day allocation by city size
- [x] Open-jaw flight detection (fly into A, out of C)
- [x] Hub city awareness for cheaper first/last legs
- [x] Train/bus suggestion for short hops (<500km)
- [x] Cluster-based optimization for 5+ cities
- [x] Add `references/multi-city.md`

## v1.5.0 ✅ — Travel Intel
- [x] Weather forecasts via wttr.in + best travel season patterns by region
- [x] Visa quick reference with passport-power tiers
- [x] Currency, cards, ATMs, and tipping culture by region
- [x] Local transport guides: airport transfers + city transit for major cities
- [x] Safety notes (scams, neighborhoods, health) when relevant
- [x] Power plugs and connectivity (SIM/eSIM, WiFi)
- [x] Concise presentation format (8-12 lines, first-time visitor essentials)
- [x] Add `references/travel-intel.md`

## Future Ideas
- [ ] Property/rental search (Idealista, Fotocasa — when APIs become available)
- [ ] Train search (Trainline, Renfe APIs)
- [ ] Bus search (Flixbus, ALSA APIs)
- [ ] Travel alerts and price tracking
- [ ] Packing list generator based on destination + weather


path: references/airbnb.md
content: # Airbnb — Short-Stay & Apartment Search

Airbnb is **optional** and runs as a **separate local MCP server** that the user installs independently.

Use it when the user wants:
- apartments, homes, villas, cabins, unique stays
- kitchen / washer / longer stay convenience
- family or group travel needing multiple rooms
- workcations / digital nomad stays
- to compare **Airbnb vs hotel** for the same destination and dates

## Install / Run

Airbnb MCP is a separate package (`@openbnb/mcp-server-airbnb`). The user must install it themselves before use. Node.js 18+ required.

**Installation (user must run manually):**
```bash
npm install -g @openbnb/mcp-server-airbnb
```

**MCP config (after installation):**
```json
{
  "mcpServers": {
    "airbnb": {
      "command": "mcp-server-airbnb"
    }
  }
}
```

Respects robots.txt by default. Do not override this.

## Tools

### `airbnb_search`

Search Airbnb listings.

Parameters:
- `location` (required) — e.g. `"Barcelona, Spain"`
- `placeId` (optional) — Google Maps Place ID, overrides location
- `checkin` / `checkout` (optional) — `YYYY-MM-DD`
- `adults`, `children`, `infants`, `pets` (optional)
- `minPrice`, `maxPrice` (optional) — nightly price range
- `cursor` (optional) — pagination

### `airbnb_listing_details`

Fetch listing details.

Parameters:
- `id` (required)
- `checkin` / `checkout` (optional)
- `adults`, `children`, `infants`, `pets` (optional)

Returns rich details such as amenities, policies, highlights, location data, and direct link.

## When Airbnb Beats Hotels

Airbnb often wins on **value** when any of these are true:
- stay is **4+ nights**
- **2+ travelers** sharing one place
- kitchen / laundry matters
- the user wants neighborhood feel over hotel services
- family / friend group wants common space
- longer stay or workcation

Hotels often win when:
- trip is short (1-3 nights)
- user wants easy check-in, daily cleaning, breakfast, concierge
- solo traveler needs convenience over space
- strict central location matters most

## Airbnb vs Hotel Comparison Workflow

```
1. Search hotels (Skiplagged + Trivago)
2. Search Airbnb listings for same location + dates
3. Compare by value, not price alone
4. Recommend ONE best-value option overall
5. Present hotel + Airbnb alternatives with trade-offs
```

## Airbnb Value Scoring

For Airbnb, score on:

- **Nightly price / total price**
- **Entire place vs room** (entire place bonus for couples/groups)
- **Location / neighborhood fit**
- **Amenities** (kitchen, washer, WiFi, AC, workspace, self check-in)
- **Space value** (bedrooms, common space, privacy)
- **Policies** (cancellation, house rules)

Heuristic:
- solo / short stay → hotels usually get a convenience bonus
- couples / 4-7 nights → balanced
- groups / families / long stay → Airbnb gets a strong value bonus

## Presentation Pattern

When comparing:

```text
🏆 BEST VALUE: [option]
- Why: [space/location/price/convenience summary]

🏨 Best hotel:
- [name] — $X/night — [key strength]
- Link: ...

🏠 Best Airbnb:
- [listing title/type] — $X/night — [key strength]
- Link: ...

Trade-off:
- Hotel = easier + more service
- Airbnb = more space + better for [group/longer stay]
```

## Defaults

If user does **not** specify accommodation style:
- **solo + short trip (1-3 nights)** → favor hotels
- **couple + 4-7 nights** → compare both equally
- **family/group + 3+ nights** → favor Airbnb in value scoring
- **digital nomad / workcation / month+** → Airbnb first, hotels as fallback

## Best Practices

- Always compare Airbnb against hotels for the same dates before recommending.
- Prefer **entire place** when privacy matters.
- Mention if Airbnb value comes from space rather than raw price.
- Flag missing essentials when relevant: WiFi, AC, kitchen, washer, self check-in.
- If user mentions pets, explicitly search with `pets` and prioritize pet-friendly stays.
- For longer stays, emphasize kitchen + laundry + workspace.


path: references/ferries.md
content: # Ferryhopper — Ferry Search

MCP endpoint: `https://mcp.ferryhopper.com/mcp`

Covers 33 countries and 190+ ferry operators.

## Setup

```bash
# Initialize and capture session
curl -s -X POST "https://mcp.ferryhopper.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -D /tmp/ferry-headers.txt \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"openclaw","version":"1.0"}}}'

SESSION=$(grep -i "mcp-session-id:" /tmp/ferry-headers.txt | awk '{print $2}' | tr -d '\r')
```

## Tools

### get_ports

List available ports and their details. Use to find port IDs.

```bash
curl -s -X POST "https://mcp.ferryhopper.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SESSION" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
    "params":{"name":"get_ports","arguments":{}}}'
```

### get_direct_connections_for_ports

Find which ports have direct ferry connections.

```bash
curl -s -X POST "https://mcp.ferryhopper.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SESSION" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call",
    "params":{"name":"get_direct_connections_for_ports","arguments":{
      "portId":"PIRAEUS"
    }}}'
```

### search_trips

Search available ferry trips between two ports on a specific date.

```bash
curl -s -X POST "https://mcp.ferryhopper.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SESSION" \
  -d '{"jsonrpc":"2.0","id":4,"method":"tools/call",
    "params":{"name":"search_trips","arguments":{
      "originPortId":"PIRAEUS",
      "destinationPortId":"SANTORINI",
      "date":"2026-07-15"
    }}}'
```

## Common Routes
- Greek Islands (Piraeus → Santorini, Mykonos, Crete, etc.)
- Italy (Naples → Capri, Sicily, Sardinia)
- Spain (Barcelona → Balearic Islands)
- Croatia (Split → Hvar, Dubrovnik ferries)
- Scandinavia (Stockholm → Helsinki, Tallinn)
- UK (Dover → Calais)

## Tips
- Get port IDs first with `get_ports`
- Check connections with `get_direct_connections_for_ports` before searching trips
- Date format: `YYYY-MM-DD`
- Ferry is often cheaper and more scenic for island routes
- Consider ferry + flight combos for Greek island hopping


path: references/flights.md
content: # Kiwi.com — Flight Search

MCP endpoint: `https://mcp.kiwi.com`

## Setup

```bash
# Initialize session (required first)
INIT=$(curl -s -X POST "https://mcp.kiwi.com" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -D /tmp/kiwi-headers.txt \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"openclaw","version":"1.0"}}}')

# Extract session ID
SESSION=$(grep -i "mcp-session-id:" /tmp/kiwi-headers.txt | awk '{print $2}' | tr -d '\r')
```

## Tool: search-flight

Search for flights between two locations.

### Parameters

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| flyFrom | string | ✅ | City name or airport code |
| flyTo | string | ✅ | City name or airport code |
| departureDate | string | ✅ | `dd/mm/yyyy` format |
| departureDateFlexRange | int | ❌ | 0-3 days flexibility |
| returnDate | string | ❌ | `dd/mm/yyyy` for round trip |
| returnDateFlexRange | int | ❌ | 0-3 days flexibility |
| passengers | object | ❌ | `{"adults":1,"children":0,"infants":0}` |
| cabinClass | string | ❌ | M (economy), W (premium), C (business), F (first) |
| sort | string | ❌ | price, duration, quality, date |
| curr | string | ❌ | EUR, USD, GBP, etc. |
| locale | string | ❌ | en, es, de, fr, etc. |

### Example: One-way flight

```bash
curl -s -X POST "https://mcp.kiwi.com" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SESSION" \
  -d '{
    "jsonrpc":"2.0","id":2,"method":"tools/call",
    "params":{"name":"search-flight","arguments":{
      "flyFrom":"Oviedo",
      "flyTo":"Rome",
      "departureDate":"10/04/2026",
      "sort":"price",
      "curr":"EUR"
    }}
  }'
```

### Example: Round trip with flexibility

```bash
curl -s -X POST "https://mcp.kiwi.com" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SESSION" \
  -d '{
    "jsonrpc":"2.0","id":3,"method":"tools/call",
    "params":{"name":"search-flight","arguments":{
      "flyFrom":"Madrid",
      "flyTo":"Tokyo",
      "departureDate":"15/05/2026",
      "departureDateFlexRange":3,
      "returnDate":"30/05/2026",
      "returnDateFlexRange":3,
      "cabinClass":"C",
      "sort":"price",
      "curr":"EUR"
    }}
  }'
```

### Response Structure

Each flight in the response array:

```json
{
  "flyFrom": "OVD",
  "flyTo": "FCO",
  "cityFrom": "Asturias",
  "cityTo": "Rome",
  "departure": { "utc": "...", "local": "..." },
  "arrival": { "utc": "...", "local": "..." },
  "totalDurationInSeconds": 21000,
  "price": 66,
  "deepLink": "https://on.kiwi.com/...",
  "currency": "EUR",
  "layovers": [
    {
      "at": "AGP",
      "city": "Málaga",
      "arrival": { "utc": "...", "local": "..." },
      "departure": { "utc": "...", "local": "..." }
    }
  ]
}
```

### Tips
- Kiwi excels at **creative routing** — combining different airlines for cheaper fares
- Use city names (not just IATA codes) — Kiwi resolves them automatically
- Set `departureDateFlexRange: 3` to find cheaper nearby dates
- Always use `sort: "price"` unless user specifically wants fastest


path: references/google-flights.md
content: # Google Flights via fli

`fli` is a Python library that reverse-engineers Google Flights' internal API. No scraping, no browser, direct API access.

## Installation

The `fli` package must be installed separately by the user before use:

```bash
pip install flights
```

Binaries after installation: `fli` (CLI) and `fli-mcp` (MCP server)

## As MCP Server

```bash
# STDIO mode
fli-mcp

# HTTP mode (streamable)
fli-mcp-http  # serves at http://127.0.0.1:8000/mcp/
```

MCP config for Claude Code / OpenCode:
```json
{
  "mcpServers": {
    "fli": {
      "command": "fli-mcp"
    }
  }
}
```

## MCP Tools

### search_flights

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| origin | string | ✅ | IATA code (e.g., 'JFK') |
| destination | string | ✅ | IATA code (e.g., 'LHR') |
| departure_date | string | ✅ | `YYYY-MM-DD` |
| return_date | string | ❌ | For round trips |
| cabin_class | string | ❌ | ECONOMY, PREMIUM_ECONOMY, BUSINESS, FIRST |
| max_stops | string | ❌ | ANY, NON_STOP, ONE_STOP, TWO_PLUS_STOPS |
| departure_window | string | ❌ | Time window `HH-HH` (e.g., '6-20') |
| airlines | list | ❌ | Filter by codes (e.g., ['BA', 'AA']) |
| sort_by | string | ❌ | CHEAPEST, DURATION, DEPARTURE_TIME, ARRIVAL_TIME |
| passengers | int | ❌ | Number of adults |

### search_dates

Find cheapest dates across a range.

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| origin | string | ✅ | IATA code |
| destination | string | ✅ | IATA code |
| start_date | string | ✅ | Range start `YYYY-MM-DD` |
| end_date | string | ✅ | Range end `YYYY-MM-DD` |
| trip_duration | int | ❌ | Days (for round-trips) |
| is_round_trip | bool | ❌ | Round trip search |
| cabin_class | string | ❌ | ECONOMY, etc. |
| max_stops | string | ❌ | ANY, NON_STOP, etc. |
| sort_by_price | bool | ❌ | Sort by price |

## CLI Usage

```bash
# Basic search
fli flights JFK LHR 2026-04-25

# Advanced search
fli flights JFK LHR 2026-04-25 \
  --time 6-20 \
  --airlines BA KL \
  --class BUSINESS \
  --stops NON_STOP \
  --sort DURATION

# Cheapest dates
fli dates JFK LHR --from 2026-04-01 --to 2026-05-01

# Specific days only
fli dates JFK LHR --from 2026-04-01 --to 2026-05-01 --monday --friday
```

## When to Use fli vs Kiwi/Skiplagged

- **fli**: Widest airline coverage (Google Flights data), best for specific airline filters, non-stop searches, cabin class filtering
- **Kiwi**: Best for creative routing (mixing airlines), European budget carriers
- **Skiplagged**: Best for hidden city fares, flexible "anywhere" searches

## Tips
- Requires the user to install `flights` package separately before use
- Uses IATA codes only (not city names) — resolve first
- Google Flights has the widest coverage of any flight search
- `search_dates` is incredibly useful for flexible travelers
- Built-in rate limiting and retries


path: references/hotels.md
content: # Trivago — Hotel & Accommodation Search

MCP endpoint: `https://mcp.trivago.com/mcp`

## Setup

```bash
# Initialize and capture session
curl -s -X POST "https://mcp.trivago.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -D /tmp/trivago-headers.txt \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"openclaw","version":"1.0"}}}'

SESSION=$(grep -i "mcp-session-id:" /tmp/trivago-headers.txt | awk '{print $2}' | tr -d '\r')
```

## Tools

### trivago-accommodation-search

Search hotels by destination name.

```bash
curl -s -X POST "https://mcp.trivago.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SESSION" \
  -d '{
    "jsonrpc":"2.0","id":2,"method":"tools/call",
    "params":{"name":"trivago-accommodation-search","arguments":{
      "query":"Rome",
      "checkin":"2026-04-10",
      "checkout":"2026-04-14",
      "adults":2,
      "rooms":1
    }}
  }'
```

### trivago-accommodation-radius-search

Search hotels near specific coordinates.

```bash
curl -s -X POST "https://mcp.trivago.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SESSION" \
  -d '{
    "jsonrpc":"2.0","id":3,"method":"tools/call",
    "params":{"name":"trivago-accommodation-radius-search","arguments":{
      "latitude":41.9028,
      "longitude":12.4964,
      "radius":5000,
      "checkin":"2026-04-10",
      "checkout":"2026-04-14",
      "adults":2
    }}
  }'
```

### trivago-search-suggestions

Get location suggestions for autocomplete.

```bash
curl -s -X POST "https://mcp.trivago.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SESSION" \
  -d '{
    "jsonrpc":"2.0","id":4,"method":"tools/call",
    "params":{"name":"trivago-search-suggestions","arguments":{
      "query":"Rome"
    }}
  }'
```

## Tips
- Trivago compares prices across multiple booking sites (Booking.com, Expedia, Hotels.com, etc.)
- Use `trivago-search-suggestions` first if unsure about exact location name
- Use radius search for "hotels near X landmark" queries
- Session required — initialize first and keep session ID
- Good for price comparison when user wants the best hotel deal


path: references/multi-city.md
content: # Multi-City Optimizer — Cheapest Route Across Multiple Destinations

Find the optimal order and routing for trips with 2+ cities.

## When to Use

- "I want to visit Rome, Paris, and Amsterdam in 10 days"
- "What's the cheapest order to do Barcelona → Prague → Berlin?"
- "Plan a 3-week Europe trip hitting London, Lisbon, and Athens"
- "Eurotrip with 5 cities, what's the best route?"

## The Problem

With N cities, there are N! possible orderings. For 4 cities that's 24 routes. For 5 it's 120. Checking every combination by searching flights would be too many API calls. Instead, use a smart heuristic.

## Optimization Strategy

### Step 1: Collect Cities

Extract all destinations from the user request. Also note the **origin** (home city) since the trip starts and ends there.

### Step 2: Build Price Matrix

For N cities, search the key inter-city flights to build a rough price map. Focus on:

1. **Origin → each city** (potential first stops)
2. **Each city → origin** (potential last stops)
3. **Between adjacent/likely pairs** (not every permutation)

Use Kiwi for this — it handles city names directly and returns quickly. Use a fixed date for comparison (midpoint of their travel window).

For 3 cities (A, B, C) from origin O, search:
```
O→A, O→B, O→C          (3 outbound options)
A→B, A→C                (2 inter-city from A)
B→A, B→C                (2 inter-city from B)
C→A, C→B                (2 inter-city from C)
A→O, B→O, C→O          (3 return options)
```
Total: 13 searches for 3 cities. Manageable.

For 4+ cities, reduce by only checking geographically sensible pairs:
- Cluster nearby cities (Rome+Barcelona = Southern Europe cluster)
- Search within clusters + between cluster endpoints
- Skip obviously bad routes (don't fly London→Athens→London→Rome)

### Step 3: Score Routes

For each viable route ordering, calculate:

```
Route cost = sum of all flight segments
Route time = sum of flight durations + layover time
```

**Geographic logic bonus:** Routes that flow geographically (west→east, north→south, or in a loop) get a bonus because:
- Fewer backtrack flights
- More logical travel flow
- Often cheaper due to shorter distances

### Step 4: Allocate Days

Distribute days across cities based on:

**City size heuristic:**
- Major capital / mega-destination (Paris, Tokyo, London, NYC): 3-4 days minimum
- Mid-size destination (Barcelona, Prague, Lisbon, Amsterdam): 2-3 days
- Small city / day-trip-able (Toledo, Bruges, Sintra): 1 day
- Transit/stopover: 0.5-1 day

**User preferences override:** If user says "I want more time in Rome", respect that.

**Travel days:** Each inter-city flight burns ~half a day. Account for this.

Formula:
```
Available activity days = total days - (number of flights × 0.5)
Distribute proportionally by city importance, respecting minimums.
```

### Step 5: Present the Optimized Route

```
🗺️ MULTI-CITY TRIP — [N] cities, [D] days

📍 Optimized route:
[Origin] → City 1 (X days) → City 2 (X days) → City 3 (X days) → [Origin]

✈️ Flights:
1. [Origin] → City 1 | [date] | $XX — [link]
2. City 1 → City 2 | [date] | $XX — [link]
3. City 2 → City 3 | [date] | $XX — [link]
4. City 3 → [Origin] | [date] | $XX — [link]
Total flights: $XXX

💡 Why this order:
- [Reason: geographic flow, cheapest combo, etc.]
- Saved $XX vs reverse order
- Alternative: [other route] would cost $XX more but [trade-off]

📅 Day allocation:
- City 1: [X] days ([dates])
- City 2: [X] days ([dates])
- City 3: [X] days ([dates])
```

Then generate a day-by-day itinerary for each city using the trip planner workflow (see `references/trip-planner.md`).

## Optimization Rules

1. **Always start from origin and return to origin** unless user specifies one-way.
2. **Minimize backtracking.** Rome→Paris→Barcelona is better than Rome→Barcelona→Paris (geographically).
3. **Check hub cities.** If a city is a major hub (London, Frankfurt, Istanbul, Dubai), it may be cheaper as first or last stop due to more flight options.
4. **Consider open-jaw.** Flying into City A and out of City C (without returning to A) is often cheaper than a loop. Present this option when relevant.
5. **Budget airlines between nearby cities.** Intra-Europe, budget carriers (Ryanair, EasyJet, Vueling) dominate short hops. Kiwi excels at finding these.
6. **Train alternatives for short hops.** Paris→Amsterdam, Barcelona→Madrid, Rome→Florence — sometimes the train is better. Mention when distance is <500km.
7. **Don't over-optimize.** If two routes differ by <$20, recommend the one with better flow/convenience, not the marginally cheaper one.

## Edge Cases

**2 cities:** Simple. Search Origin→A→B→Origin vs Origin→B→A→Origin. Pick cheaper.

**5+ cities:** Group into 2-3 geographic clusters. Optimize cluster order, then city order within clusters. This reduces search space dramatically.

**Flexible dates:** If user is flexible, search the cheapest departure date for the first leg, then build forward from there.

**One-way / no return:** User relocating or continuing elsewhere. Skip return leg, optimize the chain only.

**Mixed transport:** For short hops (<500km), mention train/bus as alternative. "Rome→Florence: $85 flight OR $35 train (1.5h, city-center to city-center)."


path: references/price-tools.md
content: # Smart Price — Find the Best Deal, Every Time

The core philosophy: **best value = optimal intersection of price, quality, and convenience.** Not the cheapest. Not the most expensive. The smartest choice.

## Value Score System

Every option (flight, hotel, car) gets a mental **value score** based on:

```
Value = Quality ÷ Price × Convenience Factor
```

Where:
- **Quality:** rating, stars, airline reputation, reviews, amenities
- **Price:** total cost including hidden fees, taxes, baggage
- **Convenience:** duration, stops, location, check-in time, cancellation policy

The best option is the one with the **highest value score**, not the lowest price.

### Example — Flights
```
Option A: $120, 8h, 2 stops, budget airline, no baggage → score: low
Option B: $180, 4h, 1 stop, good airline, baggage included → score: HIGH ✅
Option C: $450, 3h, direct, premium airline → score: medium (overkill for most)
```
Recommend B. Mention A as budget alternative and C as premium option.

### Example — Hotels
```
Option A: $60/night, 6.5/10, far from center → score: low
Option B: $95/night, 8.8/10, walkable to everything → score: HIGH ✅  
Option C: $250/night, 9.2/10, luxury, pool, spa → score: medium (premium tier)
```
Recommend B. Mention A and C as alternatives.

## Price Calendar — Finding the Cheapest Dates

When user is flexible on dates ("when is it cheapest?", "sometime in June", "best time to go"):

### Method 1: Skiplagged Flex Calendar (fastest)

```bash
# Flexible departure dates
curl -s -X POST "https://mcp.skiplagged.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc":"2.0","id":1,"method":"initialize",
    "params":{"protocolVersion":"2025-06-18","capabilities":{},
    "clientInfo":{"name":"openclaw","version":"1.0"}}
  }' > /dev/null

curl -s -X POST "https://mcp.skiplagged.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc":"2.0","id":2,"method":"tools/call",
    "params":{"name":"[REDACTED_SECRET]","arguments":{
      "origin":"MAD",
      "destination":"FCO",
      "depart_date":"2026-06-01"
    }}
  }'
```

This returns a calendar grid showing the cheapest fare for each day around the target date. Present as:

```
📅 Cheapest dates to fly MAD → FCO in June:
- Jun 3 (Tue): $45 ← cheapest! 🔥
- Jun 4 (Wed): $52
- Jun 5 (Thu): $89
- Jun 10 (Mon): $48
- Jun 15 (Sun): $62
- Jun 20 (Fri): $112 (avoid weekends)
```

### Method 2: Skiplagged Return Calendar (round trip optimization)

After finding cheap departure dates, optimize the return:

```bash
curl -s -X POST "https://mcp.skiplagged.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc":"2.0","id":3,"method":"tools/call",
    "params":{"name":"[REDACTED_SECRET]","arguments":{
      "origin":"MAD",
      "destination":"FCO",
      "depart_date":"2026-06-03",
      "trip_length":7
    }}
  }'
```

### Method 3: Kiwi Flex Range (±3 days)

```bash
# Search with departureDateFlexRange: 3 to check nearby dates
# See references/flights.md for full params
```

### Method 4: Skiplagged "Anywhere" (cheapest destination)

When user says "where should I go?" or "surprise me with something cheap":

```bash
curl -s -X POST "https://mcp.skiplagged.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc":"2.0","id":4,"method":"tools/call",
    "params":{"name":"[REDACTED_SECRET]","arguments":{
      "origin":"MAD",
      "depart_date":"2026-06-01"
    }}
  }'
```

## Cross-Provider Comparison — The Core Engine

**Always search multiple providers and present the single best option.** This is what makes the skill valuable — the user doesn't have to check 4 websites.

### Flight Comparison Workflow

```
1. Search Kiwi (creative routing, budget airlines)
   ↓
2. Search Skiplagged (hidden city fares)
   ↓
3. Deduplicate (same route + similar time = same flight)
   ↓
4. Score each option (price × duration × stops × airline quality)
   ↓
5. Present: 🏆 Best Value + 💸 Cheapest + ⚡ Fastest
```

#### Execution — Parallel Search

Search both providers in one turn. Both are independent, no dependency:

**Kiwi:**
```bash
# Initialize + search (see references/flights.md)
# Sort by price, get top results
```

**Skiplagged:**
```bash
# Initialize + resolve IATA + search (see references/skiplagged.md)
# Get top results
```

#### Deduplication Rules

Two results are the "same flight" if:
- Same departure airport + arrival airport
- Departure time within 30 minutes
- Same number of stops

When duplicated: keep the cheaper one, note which provider had the better price.

#### Scoring Heuristic

For each unique flight, compute a mental value rank:

**Price weight: 40%** — lower is better, normalize within result set
**Duration weight: 30%** — shorter is better
**Stops weight: 15%** — fewer is better (0 stops = best, 2+ = worst)
**Convenience weight: 15%** — departure time (red-eye penalty), airline reputation, baggage included

Winner = highest combined score → label as 🏆 **Best Value**

### Accommodation Comparison Workflow

```
1. Search Skiplagged hotels
   ↓
2. Search Trivago hotels
   ↓
3. If apartments/homes/longer stay/group travel matter, also search Airbnb (see airbnb.md)
   ↓
4. Score by value, not price alone
   ↓
5. Present ONE best-value stay overall + hotel/Airbnb alternatives
```

#### Hotel Scoring

**Rating weight: 35%** — higher is better, minimum 7.0 for recommendations
**Price weight: 35%** — lower is better per night
**Location weight: 20%** — proximity to city center / user's vibe area
**Amenities weight: 10%** — WiFi, breakfast, pool, gym (bonus points)

Reject any hotel below 7.0 rating unless budget tier with nothing better.

#### Airbnb Scoring

Read `references/airbnb.md` for tool details. Use Airbnb especially when the user wants more space, a kitchen, group travel, longer stays, or neighborhood feel.

**Space/privacy weight: 30%** — entire place, bedrooms, common area
**Price weight: 25%** — nightly + total stay value
**Location weight: 20%** — neighborhood fit and convenience
**Amenities weight: 15%** — kitchen, washer, WiFi, workspace, AC, self check-in
**Policy/convenience weight: 10%** — cancellation, check-in ease, house rules

For solo short stays, hotels usually get a convenience bonus. For groups or 4+ nights, Airbnb often gets a value bonus.

### Car Rental Comparison

Only Skiplagged currently. Present sorted by price with car type noted:

```
🚗 Car Rentals [City] — [dates]
- Economy (Fiat 500): $25/day — [link]
- Compact (VW Golf): $32/day — [link]  ← 🏆 best value for most
- SUV (Nissan Qashqai): $48/day — [link]
```

## Presenting Comparison Results

Always lead with the **single best recommendation**, then alternatives:

```
🏆 BEST DEAL: [Flight/Hotel name]
   $XXX | [key details] | [why it's the best]
   🔗 Book: [link]

Also good:
- 💸 Cheapest: [option] — $XXX [trade-off note]
- ⚡ Fastest: [option] — $XXX [trade-off note]
- 💎 Premium: [option] — $XXX [what you get extra]
```

**Key rules:**
- **Never dump raw results.** Always curate, score, and recommend.
- **Explain the trade-offs.** "€30 cheaper but 4 hours longer" helps the user decide.
- **Include booking links for every option.** The user should be able to act immediately.
- **Flag hidden costs.** Budget airlines without baggage, hotels without breakfast, car rentals without insurance.
- **Mention price trends if relevant.** "Prices for this route are typically €X cheaper in [month]."

## Price Alert Patterns

When a deal is exceptionally good, flag it:

```
🔥 DEAL ALERT: This is 40% below average for this route!
```

Use these rough benchmarks for "good deal" detection:
- Intra-Europe flights under €50 one-way = great deal
- Transatlantic flights under $400 round trip = great deal
- Asia flights under $600 round trip from Europe = great deal
- Hotels in major cities under $80/night with 8+ rating = great deal

## Decision Tree — What to Search When

```
User wants flights
├── Specific dates → Kiwi + Skiplagged parallel search
├── Flexible dates → [REDACTED_SECRET] first, then search best dates
├── Flexible destination → [REDACTED_SECRET]
└── Round trip optimization → [REDACTED_SECRET]

User wants hotels / stays
├── Specific city + dates → Skiplagged + Trivago parallel search
├── Apartments / homes / long stay / group trip → also use Airbnb (see airbnb.md)
├── "Near [landmark]" → Trivago radius search
└── Budget comparison → search all relevant providers, score, recommend

User wants cars
└── Skiplagged sk_cars_search → sort by price, group by type

User wants "best way from A to B"
├── Search flights (Kiwi + Skiplagged)
├── Check if ferry makes sense (coastal/island route → Ferryhopper)
├── Compare: flight price+time vs ferry price+time
└── Recommend with clear trade-off explanation

User wants complete trip
└── See references/trip-planner.md (uses all of the above)
```


path: references/skiplagged.md
content: # Skiplagged — Flights, Hotels & Car Rentals

MCP endpoint: `https://mcp.skiplagged.com/mcp`

Skiplagged is stateless — no session ID needed after initialize.

## Setup

```bash
# Initialize (once per session)
curl -s -X POST "https://mcp.skiplagged.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"openclaw","version":"1.0"}}}'
```

## Tools Overview

| Tool | Purpose |
|------|---------|
| `sk_flights_search` | Search flights between specific locations |
| `[REDACTED_SECRET]` | Find cheapest destinations from departure city |
| `[REDACTED_SECRET]` | Flexible departure price calendar |
| `[REDACTED_SECRET]` | Round-trip flexible calendar |
| `sk_hotels_search` | Search hotels in a city |
| `sk_hotel_details` | Room availability and pricing |
| `sk_cars_search` | Car rental search |
| `sk_resolve_iata` | City name → IATA code |
| `sk_resolve_location` | Lat/lng → nearest airport IATA |

## Important: Resolve IATA First

Before searching flights, resolve city names to IATA codes:

```bash
curl -s -X POST "https://mcp.skiplagged.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc":"2.0","id":2,"method":"tools/call",
    "params":{"name":"sk_resolve_iata","arguments":{"input":"Rome"}}
  }'
```

Note: The parameter is `input`, not `city`.

## Flight Search

```bash
curl -s -X POST "https://mcp.skiplagged.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc":"2.0","id":3,"method":"tools/call",
    "params":{"name":"sk_flights_search","arguments":{
      "origin":"OVD",
      "destination":"FCO",
      "depart_date":"2026-04-10",
      "cabin":"economy",
      "adults":1,
      "limit":12
    }}
  }'
```

Date format: `YYYY-MM-DD`

## Flexible Anywhere Search

When user says "where can I go cheap from Madrid?":

```bash
curl -s -X POST "https://mcp.skiplagged.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc":"2.0","id":4,"method":"tools/call",
    "params":{"name":"[REDACTED_SECRET]","arguments":{
      "origin":"MAD",
      "depart_date":"2026-04-10"
    }}
  }'
```

## Flexible Price Calendar

Find cheapest departure dates:

```bash
curl -s -X POST "https://mcp.skiplagged.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc":"2.0","id":5,"method":"tools/call",
    "params":{"name":"[REDACTED_SECRET]","arguments":{
      "origin":"OVD",
      "destination":"FCO",
      "depart_date":"2026-04-10"
    }}
  }'
```

## Hotel Search

```bash
curl -s -X POST "https://mcp.skiplagged.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc":"2.0","id":6,"method":"tools/call",
    "params":{"name":"sk_hotels_search","arguments":{
      "city":"Rome",
      "checkin":"2026-04-10",
      "checkout":"2026-04-14",
      "guests":2
    }}
  }'
```

## Car Rental Search

```bash
curl -s -X POST "https://mcp.skiplagged.com/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc":"2.0","id":7,"method":"tools/call",
    "params":{"name":"sk_cars_search","arguments":{
      "pickup_location":"FCO",
      "pickup_date":"2026-04-10",
      "dropoff_date":"2026-04-14"
    }}
  }'
```

## Tips
- Skiplagged specializes in **hidden city fares** (cheaper tickets with strategic layovers)
- Always resolve IATA codes first with `sk_resolve_iata`
- Use `[REDACTED_SECRET]` when user is flexible on destination
- Use `[REDACTED_SECRET]` when flexible on dates
- Dates must be today or later (no past searches)
- Default limit is 12 for flights
- Stateless server — no session management needed after init


path: references/travel-intel.md
content: # Travel Intel — Destination Intelligence

Practical destination information to complement flight/hotel searches. Enhances trip planning with real-world context.

## When to Use

- Any trip planning (automatically append key intel to itineraries)
- "What do I need to know about traveling to Japan?"
- "Do I need a visa for Thailand?"
- "What's the weather like in Barcelona in June?"
- "How do I get around in Rome?"

## Weather

Use the weather skill or wttr.in directly:

```bash
# Current + 3-day forecast
curl -s "wttr.in/Barcelona?format=v2"

# JSON for programmatic use
curl -s "wttr.in/Barcelona?format=j1"

# One-liner
curl -s "wttr.in/Barcelona?format=%c+%t+(feels+like+%f),+%w+wind,+%h+humidity"
```

### Best Travel Seasons (general patterns)

**Mediterranean (Spain, Italy, Greece, Turkey, Croatia):**
- Best: Apr-Jun, Sep-Oct (warm, fewer crowds, lower prices)
- Peak: Jul-Aug (hot, crowded, expensive)
- Off-season: Nov-Mar (cool/rainy, cheapest, many closures)

**Northern Europe (UK, Scandinavia, Benelux, Germany):**
- Best: May-Sep (long days, mild weather)
- Peak: Jun-Aug
- Off-season: Oct-Mar (dark, cold, but Christmas markets Nov-Dec)

**Southeast Asia (Thailand, Vietnam, Bali, Philippines):**
- Best: Nov-Mar (dry season for most)
- Monsoon: Jun-Oct (varies by country; Bali's dry season is Apr-Oct)
- Cheapest: May-Jun, Sep-Oct (shoulder)

**Japan:**
- Cherry blossom: late Mar-mid Apr (crowded, book months ahead)
- Best: Mar-May, Oct-Nov (mild, beautiful)
- Avoid: Jun-Jul (rainy season), Aug (hot + humid)

**Caribbean:**
- Best: Dec-Apr (dry, peak season)
- Hurricane: Jun-Nov (cheapest, but risky)
- Sweet spot: May or early Dec

**South America:**
- Seasons reversed from Northern Hemisphere
- Patagonia: Nov-Mar only
- Amazon: Jun-Oct (dry, easier travel)
- Andes: May-Sep (dry season)

**East Africa (Kenya, Tanzania):**
- Safari best: Jun-Oct (dry, animals concentrate at water)
- Wildebeest migration: Jul-Oct (Masai Mara)

## Visa Quick Reference

The agent should use its general knowledge for visa requirements. Key patterns:

**Passport power tiers (for common origins):**

US/EU/UK/Canada/Australia/Japan passport holders:
- Visa-free or visa-on-arrival to 170+ countries
- Notable exceptions needing advance visa: Russia, China (sometimes), India, Brazil (reciprocity varies)

Latin American passports (varies widely):
- Schengen/EU: most need visa (except some like Chile, Argentina, Brazil for short stays)
- USA: most need B1/B2 visa or ESTA equivalent
- Within Latin America: mostly visa-free

**Always recommend the user verify** at their country's foreign affairs website or sites like iVisa. Visa rules change frequently.

Format:
```
🛂 Visa: [Visa-free for X days / Visa required / eVisa available]
⚠️ Verify at [official source] — rules change frequently
```

## Currency & Money

For each destination, mention:

```
💱 Currency: [name] ([code])
💳 Cards: [widely accepted / cash preferred / mixed]
🏧 ATMs: [widely available / limited]
💡 Tip: [practical money tip]
```

Key patterns the agent knows:
- **Western Europe:** EUR (most), cards widely accepted, contactless common
- **UK:** GBP, cards everywhere, almost cashless
- **Japan:** JPY, surprisingly cash-heavy despite being tech-forward, carry ¥10,000+ notes
- **Southeast Asia:** Local currency, cash preferred in markets/small shops, ATMs everywhere but fees vary
- **Latin America:** Mix of local + USD accepted in tourist areas. ATM withdrawal often best rate.
- **Turkey:** TRY, volatile exchange — check rate before going, cards accepted in cities

**Tipping patterns:**
- USA/Canada: 15-20% expected
- Europe: rounding up or 5-10%, not obligatory
- Japan: no tipping (can be offensive)
- Southeast Asia: not expected, appreciated at 10%
- Latin America: 10% standard in restaurants

## Local Transport

For each destination, provide the essential "how to get around" info:

**Airport → City:**
```
🛬 Airport transfer:
- [Best option]: [name, price, duration]
- [Alternative]: [name, price, duration]
- ⚠️ Avoid: [common tourist trap if any]
```

**Getting around:**
```
🚇 Metro/subway: [exists? passes available?]
🚌 Bus: [useful? tourist-friendly?]
🚕 Taxi/rideshare: [Uber? Bolt? local app?]
🚶 Walking: [walkable city? safe?]
🚲 Bike: [bike share? cycling culture?]
```

Key city transport patterns:
- **London:** Oyster/contactless, Tube is king, Uber works, Heathrow Express £25 vs Tube £5
- **Paris:** Navigo pass, Metro excellent, CDG: RER B €11 vs taxi €55
- **Tokyo:** Suica/Pasmo card, trains are everything, Narita Express ¥3,250
- **Rome:** Roma Pass, Metro limited but buses extensive, walk the center, Fiumicino: Leonardo Express €14
- **Barcelona:** T-Casual card, Metro good, walkable center, El Prat: Aerobus €7
- **Bangkok:** BTS/MRT for main areas, Grab (not Uber), Don Mueang: bus ฿30 vs taxi ฿300
- **NYC:** MetroCard/OMNY, subway 24/7, JFK: AirTrain+subway $10.75 vs taxi ~$70

## Safety Notes

Only mention when genuinely relevant. Do not fear-monger.

Mention if:
- Specific neighborhoods to avoid at night
- Common tourist scams for that destination
- Health precautions (mosquito-borne diseases, altitude, water safety)
- Emergency number (if not obvious)

Format:
```
⚠️ Safety:
- [Specific, actionable tip]
- Emergency: [number]
```

## Power & Connectivity

```
🔌 Plug type: [type] — [adapter needed?]
📱 SIM/eSIM: [recommendation for tourist data]
🌐 WiFi: [generally available? quality?]
```

## Presentation

When adding travel intel to a trip plan, keep it concise — a short block at the end:

```
🌍 TRAVEL INTEL — [Destination]

🌤️ Weather (Jun): 25-32°C, sunny, occasional afternoon showers
🛂 Visa: Visa-free for 90 days (US passport)
💱 Currency: EUR — cards widely accepted
🚇 Getting around: Metro + walking. Buy T-Casual (€11.35, 10 rides)
🛬 Airport: Aerobus to Plaça Catalunya, €7, 35 min
💡 Tips:
- Dinner starts at 9-10 PM (not 7!)
- Siesta 2-5 PM — many small shops close
- Tap water is safe
🔌 Plug: Type C/F (standard EU) — US travelers need adapter
```

Keep this to 8-12 lines max. Only include what's genuinely useful for a first-time visitor.


path: references/trip-planner.md
content: # Trip Planner — Universal Itinerary Generator

Generate complete, personalized trip itineraries with real prices and booking links. Adapts to any traveler, any destination, any style.

## Design Principle

Rather than listing every possible travel style, this planner uses a **dimensional profiling system**. Every trip is a unique blend of dimensions — like mixing colors. "Honeymoon in Bali" and "solo backpacking in Vietnam" both use the same framework but produce completely different results.

The agent already understands human intent. This document provides the **structured workflow** and **travel-specific knowledge** the agent needs to deliver real prices and actionable itineraries.

## Step 1: Profile the Trip

There are **two modes** for gathering trip info:

### Mode A: Quick (default)
When the user gives a direct request ("find me flights to Rome"), extract what you can from their message and **ask only what's truly missing** (usually just dates or origin). Infer everything else. Most users want fast answers, not questionnaires.

### Mode B: Guided Intake
When the user asks for a **full trip plan**, wants help deciding, or explicitly asks for a questionnaire, use this **conversational intake**. Ask in ONE message, not one question at a time:

```
Let's plan your trip! A few quick questions:

1. 📍 Where do you want to go? (city, country, or "surprise me")
2. 🛫 Where are you flying from?
3. 📅 When? (specific dates, or flexible like "sometime in June")
4. ⏱️ How many days?
5. 👥 Who's going? (solo, couple, family, friends + how many)
6. 💰 Budget range? (budget / mid-range / premium / no limit)
7. ✨ What's the vibe? What do you want to feel or experience?
   (examples: "eat everything", "chill on a beach", "see all the history",
   "party", "romantic", "adventure", or just tell me in your own words)

Answer as many or as few as you want — I'll figure out the rest!
```

**Rules for the intake:**
- **Always in ONE message.** Never drip-feed questions one by one.
- **All questions are optional except destination.** If they only answer 3 of 7, work with that.
- **Accept any format.** Full sentences, single words, emojis, bullet points — all valid.
- **Never repeat questions they already answered** in their original message.
- **Skip the intake entirely** if the user already gave enough info to work with.
- **Adapt language** to the user's language (if they write in Spanish, ask in Spanish).

After receiving answers (or partial answers), proceed to profiling:

### Core Dimensions

Every trip lives somewhere on these spectrums. The user's words place them naturally:

**Budget:** free → budget → mid-range → premium → ultra-luxury
- Infer from: price mentions, accommodation type, airline class, word choice ("cheap" vs "treat ourselves")
- Default: mid-range

**Energy:** relaxed → moderate → active → intense
- Infer from: activity mentions, trip length vs destinations, physical activities, age/group context
- Default: moderate

**Social:** solo introspective → solo social → couple → small group → large group → family
- Infer from: pronouns ("I" vs "we"), mentions of partner/kids/friends, group size
- Default: solo or couple (ask if ambiguous)

**Structure:** completely open → loose framework → planned with flexibility → tightly scheduled
- Infer from: "go with the flow" vs "I want to see everything" vs specific requests
- Default: planned with flexibility

**Focus:** This is the trip's personality — what the traveler cares about most. Unlike the spectrums above, focus is a **weighted blend** of interests. Every trip mixes multiple interests at different intensities.

Interest categories (the agent should recognize these and any related concepts, synonyms, or adjacent ideas — this list is illustrative, not exhaustive):

- **Culture & History** — museums, ruins, architecture, heritage, traditions, local customs, UNESCO sites, galleries, street art, neighborhoods with character
- **Food & Drink** — restaurants, street food, markets, cooking classes, wine, beer, coffee culture, food tours, Michelin, local specialties, dietary exploration
- **Nature & Outdoors** — hiking, parks, mountains, lakes, forests, beaches, diving, snorkeling, kayaking, cycling, skiing, surfing, camping, stargazing
- **Nightlife & Social** — bars, clubs, rooftops, live music, pub crawls, festivals, social hostels, karaoke, casino
- **Wellness & Rest** — spa, yoga, meditation, thermal baths, retreat, beach lounging, slow mornings, digital detox, hot springs, hammam
- **Romance & Intimacy** — couples dinners, sunset spots, scenic stays, privacy, honeymoon, anniversary, proposal-worthy locations
- **Shopping & Markets** — boutiques, outlets, luxury brands, flea markets, artisan crafts, souvenirs, bazaars, vintage
- **Art & Creativity** — galleries, studios, workshops, street art tours, photography spots, design districts, maker spaces
- **Sports & Events** — football, F1, tennis, surfing, marathons, Olympics, local sports, stadium tours
- **Music & Performance** — concerts, festivals, opera, jazz, flamenco, local folk, theater, busking scenes
- **Family & Kids** — theme parks, zoos, aquariums, interactive museums, playgrounds, kid-friendly everything, safety, nap schedules
- **Learning & Growth** — language classes, university tours, workshops, historical deep-dives, cultural immersion, volunteer work
- **Spirituality & Reflection** — temples, churches, mosques, pilgrimage routes, meditation, silent retreats, sacred sites
- **Photography & Visual** — viewpoints, golden hour spots, iconic landmarks, photogenic streets, drone-friendly, landscape shots
- **Wildlife & Eco** — safaris, whale watching, sanctuaries, national parks, eco-lodges, conservation, bird watching
- **Adventure & Adrenaline** — bungee, paragliding, zip-lining, canyoning, off-road, extreme sports, survival experiences
- **Work & Productivity** — coworking, WiFi quality, time zones, café culture, long-stay, bleisure, quiet hotels
- **Road Trip & Freedom** — scenic routes, car rental, vanlife, multiple stops, flexibility, countryside, coastal drives
- **Local & Authentic** — non-touristy, hidden gems, local neighborhoods, homestays, off-beaten-path, "live like a local"
- **Accessibility** — wheelchair access, limited mobility, sensory needs, medical proximity, elevator access, flat terrain
- **Pet Travel** — pet-friendly hotels, parks, transport rules, quarantine info, vet access
- **Sustainable & Eco** — low carbon, train over plane, eco-lodges, local economy, plastic-free, carbon offset

**When no focus is specified:** Default blend — 35% culture, 25% food, 20% local/walking, 10% nature, 10% rest. This satisfies the majority of travelers.

**The agent should freely interpret any user description**, including creative or unconventional requests ("I want a chaotic trip", "surprise me", "my vibe is Studio Ghibli", "dark tourism", "only free things"). The categories above are anchors, not boundaries.

### Secondary Signals (detect if mentioned, never ask)

- **Dietary needs** — vegetarian, vegan, halal, kosher, gluten-free, allergies → affects every food recommendation
- **Accommodation style** — hotel, hostel, Airbnb, resort, boutique, camping, glamping, villa, ryokan, riad → often implied by budget
- **Transport preference** — walking, public transit, taxi/rideshare, rental car, bike → affects logistics
- **Time personality** — early bird vs night owl → affects scheduling
- **Mobility/health** — anything physical → affects activity selection
- **First visit vs returning** — "I've been before" means skip the obvious tourist spots
- **Special occasions** — birthday, anniversary, graduation, retirement → add a special element

## Step 2: Search Flights

Read `references/flights.md` (Kiwi) or `references/skiplagged.md`.

Strategy by budget:
- **Budget:** Sort by price, accept layovers, use `departureDateFlexRange: 3`
- **Mid-range:** Sort by quality. Prefer ≤1 stop, reasonable duration.
- **Premium:** Sort by duration, prefer direct or business class (`cabinClass: "C"`)

Always present:
- 💸 Cheapest option
- ⚡ Fastest option
- 🎯 Best value (recommended)

Each with deep link.

## Step 3: Search Accommodation

Read `references/skiplagged.md` and/or `references/hotels.md`. If apartments, homes, longer stays, workcations, or group travel are relevant, also read `references/airbnb.md`.

Match to profile:
- **Budget:** Cheapest with decent rating (≥7.0). Mention hostels for backpackers.
- **Mid-range:** Best rating-to-price ratio. 3-4★, rating ≥8.0.
- **Premium:** Highest rated. 4-5★, unique features (pool, view, spa, design).
- **Apartment/home fit:** Prefer Airbnb when kitchen, laundry, workspace, privacy, or extra space matter.

Location priority by focus:
- Nightlife → near bar district
- Culture → near old town / museum quarter
- Food → near market district or foodie neighborhood
- Beach → oceanfront or walking distance
- Work → near coworking / business district with good WiFi
- Family → safe area, near parks / attractions

Present 2-3 options even if user specified a tier (gives choice). When Airbnb is relevant, compare **hotel vs Airbnb** directly and recommend the overall best-value stay.

## Step 4: Budget Breakdown

```
Flight:        $XXX (actual)
Hotel:         $XXX (actual, N nights)
Daily costs:   $XX/day × N days = $XXX
  ├─ Food
  ├─ Transport  
  └─ Activities
─────────────────────────────
TOTAL:         ~$X,XXX
```

### Daily Cost Benchmarks (per person, USD)

Western Europe (Paris, London, Amsterdam, Zurich): Budget $40-60 | Mid $80-130 | Premium $160+
Southern Europe (Rome, Barcelona, Lisbon, Athens): Budget $30-50 | Mid $60-100 | Premium $130+
Eastern Europe (Prague, Budapest, Krakow, Belgrade): Budget $20-35 | Mid $40-70 | Premium $100+
Scandinavia (Stockholm, Copenhagen, Oslo): Budget $50-70 | Mid $90-140 | Premium $180+
UK & Ireland: Budget $40-60 | Mid $80-130 | Premium $160+
USA & Canada: Budget $50-70 | Mid $90-150 | Premium $200+
Japan: Budget $40-60 | Mid $80-130 | Premium $170+
South Korea: Budget $30-50 | Mid $60-100 | Premium $130+
Southeast Asia (Thailand, Bali, Vietnam): Budget $15-25 | Mid $35-60 | Premium $90+
South Asia (India, Sri Lanka, Nepal): Budget $10-20 | Mid $25-50 | Premium $80+
China: Budget $20-35 | Mid $50-80 | Premium $120+
Middle East (Dubai, Doha, Amman, Oman): Budget $40-60 | Mid $80-140 | Premium $200+
Latin America (Mexico, Colombia, Argentina, Peru): Budget $15-30 | Mid $35-65 | Premium $100+
Caribbean: Budget $30-50 | Mid $60-100 | Premium $150+
Africa (Morocco, Kenya, South Africa, Egypt): Budget $15-30 | Mid $40-80 | Premium $120+
Central Asia (Georgia, Uzbekistan, Kazakhstan): Budget $15-25 | Mid $30-55 | Premium $80+
Australia & New Zealand: Budget $50-70 | Mid $90-140 | Premium $180+
Pacific Islands (Fiji, Maldives, Tahiti): Budget $40-60 | Mid $80-150 | Premium $250+

## Step 5: Build Day-by-Day Itinerary

### Daily Structure

```
📅 Day X — [Date] ([Day of week]) — [Theme/Area]
🌅 Morning: [activity]
🍽️ Lunch: [area or cuisine]
🌇 Afternoon: [activity]
🍽️ Dinner: [area or cuisine]
🌙 Evening: [optional activity]
💡 Tip: [practical tip]
```

### Rules

1. **Day 1 = Arrival.** Adjust for arrival time. Late arrival → check-in + dinner only.
2. **Last Day = Departure.** Early flight → just check-out. Late flight → morning activity.
3. **Rest day.** Include one for trips > 5 days. Day 4 or 5, lighter schedule.
4. **Cluster geographically.** Group activities by area to minimize transit.
5. **Timing awareness:** Museums early (less crowd), markets morning, parks golden hour, nightlife late (especially Southern Europe / Latin America).
6. **Match pacing to energy dimension.** Relaxed: 1-2 activities. Moderate: 2-3. Active: 4-5. Intense: dawn to midnight.
7. **Weight activities toward focus.** Foodie? Every meal is a highlight. Adventure? Day trips. Cultural? Top museums. Party? Evenings are the main event.
8. **Mention practical details:** Free entry days, best neighborhoods, local customs, tipping, safety, dress codes, reservation needs.
9. **Day trips** for 5+ day stays. One excursion to a nearby town/attraction. The agent knows popular pairings (Paris→Versailles, Madrid→Toledo, Tokyo→Kamakura, etc.).
10. **Special occasion touch.** If birthday/anniversary/honeymoon, add one special element (rooftop dinner, surprise activity, scenic spot).

## Step 6: Present

Format for chat (no markdown tables):

```
✈️ [DESTINATION] — [N] days | [DATES]
[One-line profile: "Romantic foodie getaway on a mid-range budget"]

💰 Budget
- ✈️ Flight: $XXX — [link]
- 🏨 Hotel: $XXX (N nights) — [link]
- 🍽️🚇🎟️ Daily: ~$XX × N = $XXX
- 💵 **Total: ~$X,XXX**

🏨 [Hotel] — [stars]★ [rating]/10 — $XX/night
📍 [Neighborhood] — [why it fits]

📅 Day-by-day...

🔗 Book:
- Flight: [link]
- Hotel: [link]

💡 Tips:
- [2-3 destination tips]
```

## Adaptation

The dimensional system means infinite combinations work naturally:

- "Solo digital nomad in Lisbon for a month" → budget-mid, relaxed energy, work focus, long-stay accommodation, coworking spots, café culture
- "Surprise anniversary trip under $3000" → premium within budget, romance focus, moderate energy, agent picks the destination
- "Chaotic 3-day Tokyo trip, we want to see EVERYTHING" → mid-range, intense energy, culture+food+nightlife blend, packed schedule
- "Accessible trip to Barcelona, my mom uses a wheelchair" → mid-range, relaxed energy, accessibility priority, flat-terrain attractions, elevator-access hotels
- "Dark tourism in Eastern Europe" → budget-mid, culture focus (but specifically: Chernobyl, Auschwitz, Cold War sites, bunkers), moderate energy
- "We're 8 friends doing a bachelor party in Cartagena" → mid-range, intense energy, nightlife+beach+adventure focus, large group logistics
- "Studio Ghibli vibes in rural Japan" → mid-range, relaxed energy, nature+art focus, countryside ryokans, forests, small towns, train journeys
- "I just got divorced and need to find myself" → solo, moderate energy, wellness+spirituality+nature focus, flexible structure, meaningful experiences


path: scripts/mcp-call.sh
content: #!/bin/bash
# mcp-call.sh — Helper to call MCP travel servers
# Usage: mcp-call.sh <provider> <tool> '<json_args>'
# Example: mcp-call.sh kiwi search-flight '{"flyFrom":"Madrid","flyTo":"Rome","departureDate":"10/04/2026","sort":"price","curr":"EUR"}'

set -euo pipefail

PROVIDER="${1:-}"
TOOL="${2:-}"
ARGS="${3:-{}}"

declare -A ENDPOINTS=(
  [kiwi]="https://mcp.kiwi.com"
  [skiplagged]="https://mcp.skiplagged.com/mcp"
  [trivago]="https://mcp.trivago.com/mcp"
  [ferryhopper]="https://mcp.ferryhopper.com/mcp"
)

if [[ -z "$PROVIDER" || -z "$TOOL" ]]; then
  echo "Usage: mcp-call.sh <kiwi|skiplagged|trivago|ferryhopper> <tool> '<json_args>'"
  exit 1
fi

URL="${ENDPOINTS[$PROVIDER]:-}"
if [[ -z "$URL" ]]; then
  echo "Unknown provider: $PROVIDER"
  echo "Available: ${!ENDPOINTS[*]}"
  exit 1
fi

HEADER_FILE=$(mktemp)
trap "rm -f $HEADER_FILE" EXIT

# Initialize session
curl -s -X POST "$URL" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -D "$HEADER_FILE" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"openclaw-travel","version":"1.0"}}}' > /dev/null

# Extract session ID if present
SESSION=$(grep -i "mcp-session-id:" "$HEADER_FILE" 2>/dev/null | awk '{print $2}' | tr -d '\r' || true)

# Call tool
SESSION_ARGS=()
if [[ -n "$SESSION" ]]; then
  SESSION_ARGS=(-H "Mcp-Session-Id: ${SESSION}")
fi

curl -s -X POST "$URL" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  "${SESSION_ARGS[@]}" \
  -d "{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":{\"name\":\"${TOOL}\",\"arguments\":${ARGS}}}" \
  | sed -n 's/^data: //p'


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)