Autonomad Travel vs Chelaile MCP
A side-by-side look at the Autonomad Travel and Chelaile MCP MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.
Verdict: choose Autonomad Travel for travel & transportation work as a local process; choose Chelaile MCP for travel & transportation as a local process. You can also run both side by side in one mcpServers block.
Which MCP server should you choose?
Choose Autonomad Travel when
- You need dedicated capabilities in the Travel & Transportation domain.
- You prefer a local stdio subprocess transport.
- Its auth model fits you: other.
- You have the keys it needs:
AGENT_DID, BOOKING_API_URL, IDENTITY_API_URL, REWARD_API_URL. - You want tools like
search_hotels, search_flights, search_dining.
Choose Chelaile MCP when
- You need dedicated capabilities in the Travel & Transportation domain.
- You prefer a local stdio subprocess transport.
- Its auth model fits you: No auth required.
- You want tools like
bus_list_cities, bus_get_city_config, bus_reverse_geocode.
Feature & specification comparison
Rows where the two servers differ are marked.
| Spec | ||
|---|---|---|
| Category | Travel & Transportation | Travel & Transportation |
| Quality signal | 61/100 · Good | 64/100 · Good |
| Install command | Confirmed | Confirmed |
| Transport | Local subprocess (stdio) | Local subprocess (stdio) |
| Auth | other | No auth required |
| Pricing | Free | Free |
| Required env vars | AGENT_DIDBOOKING_API_URLIDENTITY_API_URLREWARD_API_URL | None listed |
| Verified owner | Community listing | Community listing |
| GitHub stars | 2 | 23 |
| Directory activity | 4 views 0 installs 0 upvotes | 8 views 1 installs 0 upvotes |
| Tools | 7 | 15 |
| Full listing | View Autonomad Travel | View Chelaile MCP |
Tools & capabilities
Autonomad Travel tools 7
search_hotelsSearch hotels, lodging, accommodations, resorts, and places to stay for a trip. Filter by city, country, check-in/check-out dates, room type, nightly price, star rating, and amenities (pool, gym, wifi, etc.). Returns matching properties with rates, photos, and availability across 2M+ properties (LiteAPI). Use this when the user wants to book a hotel, find a place to stay, compare lodging options, or pick a resort.search_flightsSearch airline flights / airfares between two cities by date, cabin class (economy / premium economy / business / first), and number of passengers. Returns available flights from 800+ airlines (Duffel) with real-time pricing, schedules, and stops. Uses IATA airport codes (e.g., MIA, JFK, LAX, LHR). Use this when the user wants to book a flight, fly somewhere, find airfare, or compare airlines.search_diningSearch restaurants and dining options by city, date, time, cuisine, party size, neighborhood, and price range. PLANNING ONLY — this returns restaurant details and indicative availability; Autonomad does not place reservations, and the user completes any booking with the restaurant directly. Use this when the user wants to find, compare, or shortlist somewhere to eat on a trip.search_activitiesSearch tours, experiences, attractions, sightseeing, and things to do via Viator (200K+ activities worldwide). Filter by city, date range, and category (food tours, walking tours, museums, snorkeling, sailing, hiking, sunset cruises, cooking classes, day trips, etc.). Returns activities with photos, ratings, durations, and per-person pricing. Use this when the user wants to plan day activities, find tours, book experiences, fill a trip itinerary, or pick attractions.search_eventsSearch live events, concerts, sports games, theater, comedy, and shows in a city (Ticketmaster + SeatGeek catalog). Filter by city, date range, category (music / sports / arts / theater / family / comedy), and keyword (artist name, team name, show title). Use this when the user wants tickets to a concert, a sports game, a Broadway show, or any live event during their trip.create_booking_intentCreate a booking intent — returns a deep-link the user clicks to complete the booking on autonomad.ai. Signing up is free, with no trial and no subscription. ALWAYS call this instead of trying to book directly through MCP — bookings require payment + identity verification that must happen on the web. WHEN TO CALL — two distinct triggers: (a) PICK intents (flight / hotel / activity / event / trip): call AFTER the user has chosen a specific offer. (b) BROWSE intent ('experiences'): call IMMEDIATELY in the SAME assistant turn that you ran search_activities and/or search_events for a browse query. Do NOT wait for the user to ask 'where's the link?' — the user already told you they want this when they asked to browse. Showing search results without also producing the deep-link is a UX failure: it forces the subscriber to manually request something they already implicitly asked for. INTENT TYPE GUIDE — pick exactly one: - 'flight' → user picked a flight only. offer_data = the flight offer object verbatim from search_flights, PLUS a top-level `passengers: <number>` field (the number of travelers the user originally requested — search_flights individual offers don't echo this back, so you must add it explicitly). - 'hotel' → user picked a hotel only. offer_data = the hotel offer object verbatim from search_hotels (or just {city, check_in, check_out} if you want to send them to a hotel-search results page rather than a specific hotel). Include `adults: <number>` and `rooms: <number>` so the booking page pre-fills the right party size. - 'activity' → user picked a Viator activity. offer_data = the activity offer. - 'event' → user picked a Ticketmaster/SeatGeek event. offer_data = the event offer. - 'trip' → user picked MULTIPLE things together (e.g. flight + hotel for the same trip). Pack them in offer_data as { flight: { ...offer, passengers: <n> }, hotel: { ...offer, adults: <n>, rooms: <n> }, activities: [<activity_offer>, ...] } — only include the keys the user actually picked. ONE deep-link covers all of them. - 'experiences' → BROWSE intent. The user wants to look at all activities AND events for a destination + date window WITHOUT picking a specific one. STRONGLY PREFER this over picking one activity yourself when the user asks to 'browse', 'see what's available', 'look at experiences in X', or just describes a destination/date range with no specific tour name. offer_data shape: { destination: 'City, Region', date_from: 'YYYY-MM-DD', date_to: 'YYYY-MM-DD', travelers?: <number>, activity_keywords?: [...], event_categories?: [...] }. The deep-link lands the subscriber on autonomad.ai's add-ons step with destination + dates pre-filled, where Viator activities and Ticketmaster/SeatGeek events for the area are surfaced together — and they can edit dates / traveler count inline. Use this whenever the subscriber's intent is 'show me everything', not 'I want this one specific tour'. Prefer 'trip' when the user said something like 'book me a flight and hotel for X' and you have both picked. Prefer 'experiences' when the user is asking to BROWSE activities/events without picking one (e.g. 'experiences between July 9 and July 13 near Stintino' → ONE deep-link, not 24 individual activity intents). Don't generate two separate intents (flight + hotel) for the same trip — that produces two deep-links and a confusing user experience. USER-FACING REPLY REQUIREMENTS — every time you create a booking intent, your reply text MUST include: 1. The deep_link as a clickable markdown link, e.g. '[Complete on autonomad.ai →](<deep_link>)' or 'Open: <deep_link>'. 2. That the account is free. Autonomad costs the traveller nothing — no subscription, no trial, no card required to sign up; they pay only for the travel they book. NEVER describe a trial, a free month, or Premium: none of those exist, and promising one is a claim we cannot honour. 3. The link expiry window (e.g. '~30 minutes — say the word and I'll regenerate if it lapses.'). CRITICAL: always echo the original passenger / adults / travelers count into offer_data. Without it the booking page defaults to 2 travelers regardless of what the user asked for.get_capabilitiesReturn the server's version, mode (human vs autonomous-agent), API base, and the list of currently-exposed tools. Useful for the LLM to confirm tool-schema compatibility before issuing a sequence of calls — call once at session start if you need to branch on capabilities.
Chelaile MCP tools 15
bus_list_citiesList cities supported by the realtime bus data service. Args: - hot_only (boolean, default true): return only the upstream's curated 'hot' set (~20 cities). Set false to dump the full ~480-city list (token-heavy, use sparingly). - response_format ('markdown' | 'json'): defaults to 'markdown' Returns (json): { "cities": [ { "cityId": "034", "cityName": "上海", "pinyin": "ShangHai", "supportSubway": true, "hot": true }, ... ] } Use when: the user mentions a city name and you don't have its ID. The hot set covers the top-tier cities the user almost certainly means.bus_get_city_configGet a city's runtime config: max poll interval and "arriving" time threshold. This is mostly relevant if you are deciding how aggressively to refresh — not for end-user questions about lines or stops. Args: - city_id (string, required): e.g. '034' (Shanghai), '027' (Beijing) - response_format ('markdown' | 'json') Returns (json): { "maxInterval": 30, "arrivingStationLimitSeconds": 180, "busDisplayConfig": { "lineDetail": "time#order#distance", "other": "time#order" } }bus_reverse_geocodeConvert WGS-84 lat/lng to a Chinese postal address (province, city, district, township, formatted address). Useful when you have raw GPS coordinates and need a human-readable place name, or the citycode/adcode to pass to other tools. Args: - lat (string, required): WGS-84 latitude, decimal, e.g. '31.230416' - lng (string, required): WGS-84 longitude, decimal, e.g. '121.473701' - response_format ('markdown' | 'json') Returns (json): { "formatted": "上海市黄浦区...", "province": "上海市", "city": "上海市", "district": "黄浦区", "township": "南京东路街道", "citycode": "021", "adcode": "310101" } For municipalities (Shanghai/Beijing/Tianjin/Chongqing) the upstream emits an empty 'city' value; this tool back-fills it with 'province' so the field is always a usable string.bus_get_my_locationResolve the caller's approximate location from their public IP — useful when the user asks something like "what's near me" without providing coordinates. **Precision is city-level (typically a few kilometres).** Good enough to identify the city and seed bus_get_nearby_stops with a starting guess. NOT precise enough to find the user's actual bus stop — for that, ask for a landmark/address and resolve it via bus_search. Caveats: - Resolves via ip-api.com (free tier; rate-limited but no auth). - VPN / corporate proxy → result reflects the proxy exit IP, not the user. - Cellular IPs often land on a provincial centroid. Args: - ip (string, optional): a specific IPv4/IPv6 to look up. Omit to use the mcp server process's own outbound IP (= the caller's machine when running locally). - response_format ('markdown' | 'json') Returns (json): { "lat": 31.2222, "lng": 121.4581, "gpsType": "wgs", "city": "上海", "region": "上海市", "country": "中国", "ip": "116.236.0.1", "isp": "China Telecom", "precision": "city-level (~10 km); not suitable for stop-level queries" } **Suggested workflow**: 1. Call this tool to identify the user's city (match 'city' field against bus_list_cities to get a cityId). 2. Pass lat/lng into bus_get_nearby_stops for a rough nearby list, OR ask the user to confirm a landmark and use bus_search.pois for sharper coordinates.bus_searchSearch inside a city by keyword. Returns matching lines, stations, and POIs in one call. Use this as the primary entry point when the user gives a line number, station name, or destination name without IDs. **Keyword tip**: plain "71", "71路", "地铁2号线", "陆家嘴" all work — the upstream is reasonably forgiving. If a short numeric returns empty, try appending "路". **Coordinate systems**: - 'pois' coords are GCJ-02 (use directly with bus_plan_transit) - 'stations' coords are WGS-84 (use with bus_get_nearby_stops / bus_get_line_realtime) Both are also marked with a 'gpsType' field. Args: - city_id (string, required): e.g. '034' - keyword (string, required) - response_format ('markdown' | 'json') Returns (json): { "highlightKey": "71路", "lines": [ { "name": "71", "lineNo": "r95817", "isSubway": false, "directions": [ { "direction": 0, "lineId": "21283603183", "startSn": "延安东路外滩", "endSn": "申昆路枢纽站" }, { "direction": 1, "lineId": "21283603182", "startSn": "申昆路枢纽站", "endSn": "延安东路外滩" } ], // Compat top-level fields mirror directions[0] (or first available). "lineId": "21283603183", "direction": 0, "startSn": "延安东路外滩", "endSn": "申昆路枢纽站" }, ... ], "stations": [{ "sId":"...", "sn":"西藏中路", "lat":31.231006, "lng":121.474316, "gpsType":"wgs", "physicalStId":"...", "namesakeStId":"...", "isSubway":false }, ...], "pois": [{ "name":"71路", "address":"...", "tag":"公交线路", "district":"黄浦区", "lat":31.233021, "lng":121.49073, "gpsType":"gcj" }, ...] } **Line folding**: each entry in 'lines' is one logical line (e.g. "71路"). The two travel directions live in 'directions[]'. Pick the lineId matching your desired direction. **Subway hint**: when 'isSubway' is true, the entry carries a 'hint' field — bus_get_line_detail will return empty for these lineIds. Use bus_get_stop_detail (metros field) or bus_plan_transit instead. **Follow-ups**: - directions[i].lineId → bus_get_line_detail (full stop list, first/last/price) — non-subway only - stations[*].physicalStId + namesakeStId → bus_get_stop_detail (NOTE: a few stations lack physicalStId — typically metro-only entries with subwayV2=1. For those, use bus_get_nearby_stops to resolve the bus platform IDs nearby.) - pois[*].lat/lng (GCJ) → bus_plan_transit as origin/destinationbus_search_morePaginated 'see more' for one category from bus_search. Args: - city_id (string, required) - keyword (string, required): same keyword used in bus_search - type ('1'|'2'|'3'): 1=more lines, 2=more stations, 3=more POIs (default '1') - response_format ('markdown' | 'json') Returns: same shape as bus_search but only the requested category is populated.bus_get_nearby_stopsList bus stops near a WGS-84 GPS coordinate, each annotated with the lines that pass through and the realtime buses approaching. **If you don't have coordinates**: call bus_get_my_location first (city-level precision via IP), or ask the user for a landmark and resolve it via bus_search.pois — the resulting lat/lng goes into this tool's lat/lng args. Args: - city_id (string, required): e.g. '034' - lat / lng (string, required): WGS-84 decimal coordinates - limit (number, default 5): how many of the closest stops to return (max 20) - response_format ('markdown' | 'json') Returns (json): { "stops": [ { "sId": "021-15232", "sn": "西藏中路", "distance": 87, "isSubway": false, "physicalStId": "...", "namesakeStId": "...", "firstLineId": "...", "lines": [ { "lineId": "...", "name": "71", "direction": 0, "endSn": "...", "status": "等待发车" | "不在运营时间" | "" (running), "preArrivalTime": "10:10" | undefined, "targetOrder": 2, "targetStationId": "021-15232", "buses": [ { "busId": "...", "order": 2, "arrivalTime": 1779070466055, "travelTime": 25, "distanceToDest": 90, "capacity": 0 } ] } ], "subwayLines": [ { "name": "地铁2号线", "shortName": "2号线", "color": "140,194,32", "directions": [{ "destName": "...", "firstTime": "05:31", "lastTime": "23:24" }] } ] } ] } Field notes: - buses[].arrivalTime is a ms timestamp; -1 = unknown - buses[].travelTime is seconds remaining; -1 = unknown - buses[].capacity: 0=light, 1=moderate, 2=crowded - If no realtime buses but the line is starting soon, 'preArrivalTime' will hold the next predicted dispatch ("10:12")bus_get_stop_detailFull detail for a stop: precise WGS-84 coordinates, every line that passes through (with first/last/price), realtime buses, and nearby metro lines. Args: - city_id (string, required) - physical_st_id (string, required): from bus_get_nearby_stops / bus_search - namesake_st_id (string, optional): recommended; from the same source - first_line_id (string, optional): a line to highlight - lat / lng (string, optional): caller's WGS-84 location, used to populate 'distance' - response_format ('markdown' | 'json') Returns (json): { "stations": [ { "sId": "...", "sn": "...", "lat": ..., "lng": ..., "distance": ..., "lines": [{ "lineId": "...", "name": "71", "direction": 0, "startSn": "...", "endSn": "...", "firstTime": "05:30", "lastTime": "23:30", "price": "2元", "targetOrder": 2, "buses": [...] }], "metros": [{ "name": "地铁14号线", "lineNo": "14号线", "color": "97,96,32" }] } ] } Multiple entries in stations[] mean the stop name maps to several physical platforms.bus_get_line_detailFull info for a line: rider-facing fields (name, first/last/price, stationsNum), the full ordered station list, the reverse-direction lineId, and every bus currently on the line. **Use this — not bus_get_timetable — to answer "is line X still running" or "first/last bus time" questions.** The timetable tool only has data for a small minority of lines. **Subway lines are NOT supported.** If bus_search returned a line with isSubway=true (e.g. lineId=1057 for 地铁2号线), this endpoint returns an empty payload — the response will carry `empty: true` and a `hint` field pointing at bus_get_nearby_stops / bus_plan_transit. Don't retry; route to those tools instead. Args: - city_id (string, required) - line_id (string, required): from bus_search.lines[*].lineId - lat / lng (string, optional): caller's WGS-84 coordinates - response_format ('markdown' | 'json') Returns (json): { "line": { "lineId":"...", "name":"71", "lineNo":"r95817", "direction":0, "startSn":"...", "endSn":"...", "firstTime":"05:30", "lastTime":"23:30", "price":"2元", "stationsNum":24 }, "stations": [{ "order":1, "sId":"...", "sn":"...", "wgsLat":..., "wgsLng":..., "physicalStId":"...", "namesakeStId":"...", "metros":[{"name":"地铁14号线","lineNo":"14号线","color":"97,96,32"}] }, ...], "buses": [{ "busId":"...", "order":2, "lat":..., "lng":..., "speed":5.7, "capacity":0, "distanceToWaitStn":...}], "reverseDirection": { "lineId":"...", "startSn":"...", "endSn":"...", "firstTime":"04:30", "lastTime":"22:30", "price":"2元" } | null, "depDesc": "...", "preArrivalTime": "...", "targetOrder": 24, "empty": true, "hint": "..." // present only when upstream returned no data (subway / retired line) } Each station carries: - 'order' → feed into bus_get_line_realtime / bus_list_line_buses as target_order - 'sId' → feed into bus_get_line_realtime as station_id (NOT into bus_get_stop_detail!) - 'physicalStId' + 'namesakeStId' → feed into bus_get_stop_detail to see every line through that stopbus_get_line_routePolyline coordinates for drawing a line on a map. Points with 'stopOrder' are actual stops; others are shape points between stops. Args: - city_id (string, required) - line_id (string, required) - include_shape (boolean, default false): false returns only stop markers (~25 points); true returns all shape points (~400-500). Skip unless you actually need to draw the line. - response_format ('markdown' | 'json') Returns (json): { "pointCount": 480, // total shape points upstream returned "stopCount": 23, // stop markers among them "points": [{ "lat":..., "lng":..., "stopOrder":1 }, ...] } 'points' is the filtered list — stops only by default, full polyline when include_shape=true. **Known caveat**: upstream sometimes omits the terminus stop from the polyline, so 'stopCount' may be one less than bus_get_line_detail's 'stationsNum' (e.g. 23 vs 24). Trust bus_get_line_detail for the authoritative station list; line_route is just for drawing. Markdown mode only summarises counts; request JSON to read coordinates.bus_get_line_realtimeCanonical "when will my bus arrive" tool. Returns every bus currently on the line, with the nearest one carrying an ETA to the waiting stop. **Important**: the upstream predicts an ETA for only the nearest bus heading to your stop. Buses farther up the route are returned (with position/speed/capacity) but their `eta` field is null. That's not a bug. **Args**: - city_id (string, required) - line_id (string, required): from bus_search - target_order (string, required): the waiting stop's order on the line. Source: bus_get_line_detail.stations[i].order, or bus_get_nearby_stops.stops[].lines[].targetOrder. - station_id (string, required): sId of the waiting stop - lat / lng (string, required): WGS-84 — the user's location is best; if unavailable, use the waiting stop's wgsLat/wgsLng (from line_detail.stations[i]). - response_format ('markdown' | 'json') Returns (json): { "line": { "lineId":"...", "name":"71", "direction":0, "endSn":"..." }, "targetOrder": 2, "realData": true, "buses": [ { "busId":"...", "licence":"...", "order":2, "lat":..., "lng":..., "speed":5.7, "capacity":0, "distanceToWaitStn":90, "eta":{"travelTime":25,"arrivalTime":1779070466055,"displayTime":"10:14"} }, { "busId":"...", "order":3, "lat":..., "lng":..., "speed":3, "capacity":0, "eta":null }, ... ], "note": "..." } Field notes: - The 'line' sub-object intentionally omits startSn — upstream does not return it on this endpoint. Read it from bus_get_line_detail if needed. - eta.travelTime is seconds remaining - eta.arrivalTime is a ms timestamp - eta.displayTime is a "HH:MM" hint from upstream - capacity: 0=light, 1=moderate, 2=crowdedbus_list_line_busesReturns the nearest bus heading to the anchor stop, with ETA and the bus's next stop name. **This is narrower than the name suggests.** Despite the upstream endpoint being called "busList", in practice it returns at most 1-2 buses (the imminent ones). For the FULL roster of every bus currently on the line, call **bus_get_line_detail** — its 'buses' array lists all live vehicles with positions. Use this tool when you want a quick "what's about to arrive" answer for a specific stop. Args: - city_id (string, required) - line_id (string, required) - target_order (string, required): the waiting stop's order on the line - station_name (string, required): display name of that anchor stop - response_format ('markdown' | 'json') Returns (json): { "targetOrder": 2, "buses": [ { "busId":"...", "licence":"...", "order":2, "lat":..., "lng":..., "speed":8.2, "capacity":0, "nextStop":"西藏中路", "eta":{"travelTime":214,"arrivalTime":..., "displayTime":"10:14"} } ] }- +3 more on the listing page
Ready-to-paste client configs
Paste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.
Autonomad Travel
{
"mcpServers": {
"autonomad1-autonomad-travel": {
"command": "npx",
"args": [
"-y",
"autonomad-travel"
],
"env": {
"AGENT_DID": "YOUR_AGENT_DID_HERE",
"BOOKING_API_URL": "YOUR_BOOKING_API_URL_HERE",
"IDENTITY_API_URL": "YOUR_IDENTITY_API_URL_HERE",
"REWARD_API_URL": "YOUR_REWARD_API_URL_HERE"
}
}
}
}
Chelaile MCP
{
"mcpServers": {
"peanutsplash-chelaile-mcp": {
"command": "npx",
"args": [
"-y",
"chelaile-mcp-server"
]
}
}
}
Frequently asked questions
Autonomad Travel is categorized under Travel & Transportation and uses a local stdio subprocess. Chelaile MCP belongs to Travel & Transportation and uses a local stdio subprocess. Pick Autonomad Travel for travel & transportation work and Chelaile MCP for travel & transportation.
Copy the mcpServers block from the config section on this page into your client's config (for example claude_desktop_config.json or ~/.cursor/mcp.json), then fully restart the client.
Autonomad Travel is listed as free. Auth: other. Chelaile MCP is listed as free. Auth: no auth required. If a server needs environment variables such as API keys, define them under the env key in your client's MCP config.
Yes. MCP clients support multiple servers: add autonomad1-autonomad-travel and peanutsplash-chelaile-mcp as separate keys in the same mcpServers object, and your assistant will call tools from either one.
On AllMCPs, Autonomad Travel has a quality signal of 61/100 (Good) with 4 views, 0 installs and 2 GitHub stars. Chelaile MCP has 64/100 (Good) with 8 views, 1 installs and 23 GitHub stars.