MCP server exposing a typed tool layer over the Duffel travel API — flight, stay and car-hire search for AI agents. Search-only, no booking surface.
Four tools with complete schemas and reasonable descriptions. All tools are READ_ONLY and properly registered with Zod schemas. Naming follows verb_noun pattern (resolve_place, search_flights, search_stays, search_cars). Descriptions are 100-200 chars, within baseline range (p10=34, p90=392). However, parameter descriptions are sparse, many lack context about format, constraints, or dependencies. Output schemas are not documented. Error handling returns generic fail() wrapper without recovery guidance. No tool annotations (readOnlyHint, etc.) despite all being read-only.
Resolve a city or airport name to IATA code(s) and geographic coordinates. Call this FIRST: flights need the IATA code, while stays and cars need the latitude/longitude. Picking an airport result usually gives you both.
Search hire cars via Duffel around a pickup coordinate from resolve_place. Returns available rates with vehicle, supplier and total price. Driver defaults to age 30, UK residence.
Search flight offers via Duffel. Use IATA codes from resolve_place. Omit return_date for a one-way trip. Returns the cheapest offers with price, airline, departure/arrival times and stop count.
Search accommodation via Duffel Stays around a coordinate from resolve_place. Returns the cheapest stays with name, rating and total price for the date range.
Output schemas not documented. LLMs cannot plan downstream calls or extract fields without knowing response structure. Duffel API responses are verbose; tool should document what fields are returned and their types.
Parameter descriptions lack format/constraint details. E.g., 'departure_date' says 'YYYY-MM-DD' but no description of what happens if date is in past or invalid. 'cabin_class' enum is in schema but not explained in description. LLMs need explicit guidance on valid ranges and formats.
Error handling is generic. fail() returns 'Error: <message>' without recovery guidance. Per pattern:recovery-guide, errors should tell LLM what to do next (e.g., 'Invalid IATA code. Call resolve_place() first to get valid codes.').
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 58 | 2026-07-28+ | v2 |
No tool annotations despite all tools being read-only. MCP spec supports readOnlyHint to signal safe tools. This helps agents reason about side effects and retry safety.
Result limits not enforced or documented. resolvePlace() returns slice(0, 6) but this is not mentioned in tool description. search_flights/stays/cars may return large result sets without pagination guidance. Per mxe:enforce-result-limits, cap results and document the limit.