Skip to content

Releases: felipebasurto/viajante

Viajante 1.5.2

Choose a tag to compare

@felipebasurto felipebasurto released this 19 Oct 18:08
9a00446

Added

  • Hermes Agent: integrations/hermes/ is a Portable Agent Plugins v1 package (stdio MCP server pinned to this release, plus a short skill). The landing page and the MCP skill carry the hermes mcp add line.
  • flights and MCP search_flights include a nearby-date price grid.
    --nearby-days / nearby_days is opt-in (default 0, off). Each one-way
    or round-trip query gains nearby_dates: the cheapest owned fare per day for
    ±N around the requested date, delta against that date, and cheapest: true
    on the lowest priced day. Round trips shift the outbound and return together
    and keep the trip length. The grid reuses the public date calendar (one batched
    window per query). Multi-city queries omit it. An unpriced day is not "no
    flights". The grid does not change offers.
  • Flight results include price_insight from the public Google Flights page
    already fetched (level, lowest, typical_range, page_label). level
    is Google's label (low, typical, or high) for the current price against
    its typical range. Viajante quotes that label and does not say the price will
    drop. A missing insight is null. When the heading and the page data disagree,
    price_insight is null and price_insight_error is markup_drift; the
    search still succeeds. --price-history (MCP include_price_history, default
    off) adds the page's price history. watch_price includes the current run's
    price_insight.

Viajante 1.5.1

Choose a tag to compare

@felipebasurto felipebasurto released this 19 Oct 17:22
75d73bb

Added

  • viajante feedback opens a prefilled GitHub issue with the Viajante version,
    Python version, and platform. Viajante sends nothing itself; --no-browser
    prints the link only.
  • One-way flights takes --depart-before HH:MM, --arrive-after HH:MM,
    --less-emissions, and --hide-separate-tickets (MCP search_flights:
    depart_before, arrive_after, less_emissions, hide_separate_tickets).
    Fetch auto and sweep send the clock bounds, max_duration, max_layover,
    the price cap, and the two options to Google's page. The page must echo each
    one; a missing or tighter echo is markup_drift. The local filter still runs on
    every row. Each query's JSON carries google_filters with the bounds sent. A
    price cap below Google's cheapest fare ends as no_results for the query as
    sent, because Google then lists the flights unpriced.
  • --exclude-basic-economy is refused on every path: the public page echoes no
    basic-economy filter, so viajante cannot prove it applied.

Changed

  • Detail searches click Reject only on Google's consent banner. The Accept
    selectors are gone.
  • A results page that finishes loading with no results grid and no empty state is
    markup_drift after a 20 s probe, not a 60 s timeout retried three times.
  • The Google cooldown after a 429 is a fixed 2 minutes, or the named Retry-After
    up to 30 minutes. It no longer doubles on each repeat limit.
  • Public Google Flights results pages are parsed into one HTML tree per fetch,
    not two or three, and the ds:1 data is decoded once. On a real 5.3 MB results
    page, 31 parses took 1.5 s of CPU before and 0.6 s now (median of 5 runs, the
    same 113 cards). A live search spends most of its time on the network, so the end-to-end
    gain is much smaller. The block check runs once per response, not once per caller.

Fixed

  • verify_answer no longer passes an invented amount near zero. A zero money field
    (an unnamed baggage buffer) owned any claim up to 1, and recommendation score maps
    (breakdown, weights) were read as amounts in the quote currency.
  • --help examples use future dates and no longer show --bags, which the
    public page refuses.
  • The README, usage guide, and llms.txt no longer say --bags asks Google to
    price checked bags. Only --carry-on rides the request.
  • Four CLI tests used a departure date that is now in the past.
  • The MCP initialize response reports the viajante version; it was blank.

Viajante 1.5.0

Choose a tag to compare

@felipebasurto felipebasurto released this 09 Oct 20:05
d53a6e3

Changed

  • Breaking (flight recommendation, schema 2): shortlist entries point to
    their offer by evidence_id and google_flights_url; the full offer is
    embedded only when it is not in offers (a relaxed pick). relaxation_order
    and scoring are gone, and weights appears only when prices could not be
    compared. Labels are role names: top_score, lowest_price, shortest
    (plus _distinct forms), alternative. Highlights restate returned fields
    and no longer compare ("Lowest fare among N compared" is removed). A one-way
    result with eight offers is about 23% smaller.
  • Round-trip packages: stops_count, stops, duration and
    duration_hours now describe the whole trip (worst leg's stops, summed leg
    time), null when a leg is unknown. They used to describe the outbound only.
    layover_city and layover_hours are null; per-journey layovers are in
    legs[].layovers.
  • Speed: packaged round trips read their return pages in one concurrent
    batch (about twice as fast); public-page ds:1 extraction is about 6x faster
    on a large page; MCP tools/list is about 29% smaller.
  • Consent: a declined Google consent is kept between CLI calls (only the
    SOCS cookie, 30 days, never an accepted consent), so a new process skips
    the consent round trip (3 requests to 1 in one live check on 2026-10-08).
  • MCP SDK 2.x: the server runs on MCPServer and needs mcp>=2.3.0.
    Transport settings go to run(). A failed tool is a result with is_error.
  • Split tickets take the same clock, duration, layover, via, overnight, and
    airport filters as one-way search, judged per ticket and hub connection.
  • Skiplagged: the parser reads the shape the provider actually returns,
    checked against captured responses in tests/fixtures/skiplagged/.
    hidden_city is null when Skiplagged sends no attributes.
  • Cooldown records name the viajante version and endpoint that wrote them.
  • MCP responses carry one-hour freshness hints (ttl_ms) on the catalog,
    resources, and server/discover. Progress is reported when the request has a
    progressToken.
  • Locked dependencies upgraded (mcp 2.3.0, playwright 1.63.0, pydantic
    2.14.0, curl-cffi 0.16.3, and others).
  • flights.py and models.py are split into smaller modules; viajante.models
    still exports every name and JSON is unchanged. MCP parameters are declared
    once in mcp_handlers.py.

Fixed

  • Empty vs failed: a nonstop search that returns a results page with no
    itineraries is no_results / provider_empty, not markup_drift. A search
    deadline is never retried as a fetch failure.
  • Hotels: Booking's free-cancellation filter sends fc=2 (it sent oos=1).
    A failed widening page is recorded in page_errors. A price in another ISO
    code is not relabelled; when every card does so the query is
    currency_mismatch. get_hotel_details answers inconclusively when a room
    city cannot be proven. A negated free-cancellation phrase after the words
    ("free cancellation not available") is unknown; 1.4.7 read it as free.
  • Filters: min_layover checks every connection. no_overnight /
    require_overnight any applies to hub splits. Mixed round-trip splits
    filter before choosing the cheapest pair. Round-trip packages keep both legs'
    carriers, so an excluded return carrier drops the package.
  • Prices and parsing: parse_price reads a trailing ISO code (KWD and BHD
    were 1000x too high). Non-finite stay totals and award inputs are rejected.
    Award cents-per-point refuses taxes above the cash price. Curaçao, Sint
    Maarten, and Panama origins no longer infer a currency.
  • Dates and flex: search_dates and flex typical, vs_typical, and the
    summary use every day's cheapest eligible fare before any buffer.
    sort="price" shows each day's cheapest fare. explore --month for the
    current month starts today.
  • Providers: Retry-After is finite and capped at 30 minutes. Google's
    consent page is dismissed every time it appears. A timed-out batch keeps the
    pages that arrived. The detail path stops after a block. Skiplagged errors
    are rejected once, not retried; hidden-city refuses more than 9 adults.
  • MCP: handler argument errors carry the Error executing tool <name>:
    prefix. watch_price validation no longer replays a cached search. Progress
    into a phase with a smaller total is no longer dropped.

Removed

  • The unreachable unsigned RPC transport, the legacy RPC calendar and automatic
    typical lookup, unused carrier helpers, and the never-set offer
    cheapest_date / cheapest fields.
  • The sweep-to-detail fallback for empty or failed flight queries.

Viajante 1.4.7

Choose a tag to compare

@cursor cursor released this 08 Oct 08:47
6ee0fb7

[1.4.7] - 2026-10-08

Changed

  • Round-trip date sweeps (search_dates, and search_flex with a stay) are
    much faster on long windows. Days are read in groups the size of the sweep
    concurrency (eight by default, two with VIAJANTE_SWEEP_MODE=conservative):
    each group's outbound pages go out together, then those days' return pages.
    With the default mode a 31-day window takes about 35 rounds of requests
    instead of 279 one after another.
  • A page that fails with a transport error or HTTP 5xx during a round-trip date
    sweep is retried once instead of stopping the whole window. A 429 from the
    provider still stops the remaining requests and applies the cooldown; groups
    that already finished keep their prices.
  • MCP progress for date sweeps now reports a day only after it has finished,
    so clients no longer see 31/31 before the first result arrives. A day cut
    off by the deadline is not reported as done.
  • The npm wrapper @viajante/mcp now starts the MCP server with the browser
    extra (uvx --from viajante[mcp,browser]==<version> viajante-mcp), so
    search_explore has Playwright available. Install Chromium once with
    uvx --from 'viajante[mcp,browser]==<version>' playwright install chromium.
    The viajante CLI bin is unchanged.

Added

  • The MCP guide tells assistants to pass deadline_seconds on long round-trip
    date or flex sweeps, so finished days come back early and unfinished days are
    marked with the deadline code instead of looking empty.
  • The missing-Chromium hint names the exact uvx ... playwright install chromium command for the npm/uvx setup.

Install

  • npx -y @viajante/mcp@1.4.7
  • uvx --from 'viajante[mcp,browser]==1.4.7' viajante-mcp

Viajante 1.4.6

Choose a tag to compare

@felipebasurto felipebasurto released this 07 Oct 14:32
f38b904

See the release record for transport behavior,
compatibility changes, validation, and publication verification.

Changed

  • Flight auto and sweep read Google's public results page. auto no longer
    selects Playwright based on query count or installation. Browser detail is
    explicit; a public-page failure does not fall back to detail.
  • Packaged round trips inspect at most eight outbound candidates on selected
    return pages and retain the provider's package total. Dates/flex use public
    page GETs for their explicit windows; ordinary flight searches do not launch
    a hidden 31-day typical lookup.

Added

  • VIAJANTE_SWEEP_MODE=standard|conservative controls public GET concurrency
    (8 or 2); invalid values fail before provider access.

  • Provider-block diagnostics expose endpoint host and path, HTTP/RPC status, sent state,
    attempt count, and cooldown basis. Status 13 alone does not identify its cause.

  • Public-page sweep sends --carry-on (one bag for the whole party),
    --airlines, --exclude-airlines, and --alliance, and fails the page read
    unless the page echoes each filter. Airline exclusion is also enforced
    locally because Google does not apply it; cards with no carrier evidence are
    dropped under an exclusion.

  • --trip multi --fetch detail searches multi-city packages in the browser.
    Not yet verified against the live provider.

  • explore reads destinations from the catalog request Google's public Explore
    page issues in Chromium, checking its origin and date echo.

  • Provider-block diagnostics distinguish queued requests from dispatched ones.

Fixed

  • Explore preserves HTTP 429 and Retry-After, detects status 13 in every RPC
    row/chunk, and stops pending searches after a block, including proxied calls.
  • Explore checks cancellation and deadlines during browser waits; cancelled
    responses do not write cooldowns, and a deadline never becomes provider-empty.
  • Airline filters match owned codes exactly, including returned codeshares;
    name aliases are a fallback only when codes are absent, with word boundaries.
  • Multi-city reselection rejects ambiguous or incomplete identities and uses
    the current selected row's evidence with the provider's final package total.
  • Empty flight pages still require the requested alliance's catalog echo.
  • Runtime capability flags retain boolean types, with additive transport and
    scope limits. Agent guidance matches the supported public-page filters.

Known limitations

  • Public-page sweep refuses checked bags, a zero carry-on, alliance exclusion,
    and multi-city before networking. Browser detail refuses every bag and
    carrier filter. Airline exclusion cannot prove the operating carrier of each
    segment. Explore needs Chromium, accepts only one adult in economy, and its
    catalog request often returned status 13 during validation. Round-trip results are scope-bound to at most eight outbound
    candidates. See the release record for validation boundaries.

Install the release with uvx --from 'viajante[mcp]==1.4.6' viajante-mcp or npx -y @viajante/mcp@1.4.6.

Flight-provider validation and package installation are separate evidence; multi-city detail remains unverified live.

Viajante 1.4.5

Choose a tag to compare

@felipebasurto felipebasurto released this 07 Oct 07:32
3b791ec

Viajante 1.4.5 adds flight offer re-checks, deterministic recommendation and opt-in split-ticket searches, a typed MCP result envelope, progress/cancellation/deadlines, local HTTP transport, and opt-in price history with on-demand watches.

Hotel finalist checks preserve property identity and keep fresh room quotes separate from the original shortlist price. Additional review fixes cover Unicode names, city aliases, query/offer route and date binding, provider city identity, cancelled-response cooldowns, final-fetch cancellation and three-decimal price changes.

The release exposes 22 MCP tools. Existing inputs remain compatible; the MCP SDK floor is now mcp>=1.14.1,<2.

Validation: 1,634 offline tests (two explicit macOS skips), Ruff, benchmark gate, Python 3.10–3.14 CI on both the release head and merge commit, minimum-SDK stdio smoke, and built distributions. These checks do not establish live-provider availability.

See the complete release record and changelog.

Publication completed successfully in the release workflow: PyPI, npm and both MCP Registry stdio entries are at 1.4.5. Independent public uvx and npx sessions each exposed 22 tools and reported runtime 1.4.5. The attached wheel and sdist match the public PyPI artifacts byte-for-byte.

Viajante 1.4.1

Choose a tag to compare

@felipebasurto felipebasurto released this 05 Oct 17:49
e5091a1

Added

  • Hotel schema 2 adds lodging_evidence_conflict, exposing explicit room/entire-unit contradictions while retaining the provider title and raw text. The CLI prints the conflicting labels as evidence.

Fixed

  • A room title that conflicts with an entire-home unit chip no longer proves an entire home. Both lodging kind and property type stay unknown; Google property descriptions still cannot prove the priced unit. Entire-house chips are recognized alongside cottage and villa chips.
  • Itinerary validation includes return and multi-city dates and leaves missing packaged journeys, segment counts, and layover evidence unknown.
  • Packaged flight filters are checked after attaching the next journey and before final top selection. Unknown connection locations cannot prove airport exclusions.
  • Trip totals preserve separate dated journeys and full multi-city leg identities. Answer verification binds each amount to its owned currency and cached searches refresh the evidence ledger.
  • New detail searches respect Google's machine-wide cooldown. Skiplagged 429s preserve rate-limit flags and record cooldowns after session recovery.
  • Explore reports expose per-query pricing failures separately from empty results, retain accurate coverage, avoid caching failed pricing, and print failures with the appropriate CLI exit status.
  • MCP cancellation keeps the process busy until its worker finishes. Atomic writes use unique temporary files, and nested hotel stays reject non-integer occupancy instead of coercing it.
  • The locked PyJWT dependency is updated to 2.15.1 to address the dependency audit findings.

Changed

  • Reduce all 15 async MCP adapters to parameter forwarding while preserving tool signatures, defaults, return shapes and search/lookup workers. The direct runtime tool is unchanged.
  • Remove unused internal carrier and hotel parser helpers and migrate parser tests to parse_hotels_page(...).cards.
  • Remove the redundant internal urllib/opener injection path. HTTP HTML fetches use the shared Chrome TLS client or an injected SweepHttpClient; the default path respects provider cooldown. The removed opener constructor keyword and parser wrapper were outside the supported library exports.

Validation

  • 1,074 offline tests, Ruff lint/format and offline benchmark gate passed.
  • Wheel/sdist and npm tarball builds passed; strict Twine metadata checks passed.
  • Release PR CI passed Python 3.10–3.14, lint and installed-wheel checks.

Live flight fares, browser UI and Booking navigation remain unverified. Final prices, party capacity, room allocation and cancellation terms still require provider evidence.

Publication verified

  • Main CI passed all seven jobs. Tag v1.4.1 points to e5091a1999001fb0e634e4e76e0cd2d95fc27008; main and develop are synchronized.
  • PyPI, npm and MCP Registry publication completed successfully. Independent public Registry readback confirmed version 1.4.1 with both PyPI and npm transports.
  • Public uvx and npx -y @viajante/mcp@1.4.1 installations passed real stdio checks: all 16 tools, runtime 1.4.1/schema 2, airport lookup, changed-roster grouping, exact-cent splits and preserved unallocated nights.
  • GitHub wheel/sdist assets match the public PyPI SHA-256 hashes. The public npm package matches the packed tarball's SHA-1 and SHA-512 hashes and carries the required mcpName.
  • npm propagation took several minutes. The first fresh uvx resolution preceded package-index propagation; the subsequent refreshed installation passed. No release tag or published package was replaced.

Release PR #54 · Main CI · Publication workflow

PyPI 1.4.1 · npm 1.4.1 · MCP Registry 1.4.1

Viajante 1.4.0

Choose a tag to compare

@felipebasurto felipebasurto released this 05 Oct 12:01
dcab9fc

Google Hotels navigation now uses provider entity IDs instead of click trackers that can return empty pages. Navigation links preserve requested dates, adults, rooms, currency and filters.

  • Add optional max_distance_km / --max-distance-km, requiring an explicit near point; exclude outside or unlocated properties before ranking.
  • Separate priced-unit evidence from general property descriptions. Exclude known party-size and single-unit capacity contradictions.
  • Add CLI --version, MCP get_runtime_info and hotel result viajante_version. The MCP server exposes 16 tools.
  • Strengthen agent contracts for changing nightly rosters, cancellation deadlines, dormitory exclusivity, replacement quotes and sequential searches.

Navigation context does not prove a current price, private room, room allocation or cancellation terms. Finalists still require provider verification.

Validation and publication

  • 1,043 offline tests, Ruff lint/format and offline benchmark gate passed.
  • Main CI passed all seven jobs, including Python 3.10–3.14 and installed-wheel checks.
  • Public PyPI and npm installations passed actual stdio checks for all 16 tools, runtime version, radius input and local stay arithmetic.
  • Published wheel and sdist hashes match PyPI metadata.
  • MCP Registry publisher confirmed io.github.felipebasurto/viajante version 1.4.0; independent public Registry API readback timed out.
  • Live HTTP checks validated six generated Google navigation URLs. Browser UI and Booking live navigation were not exercised.

Changes in PR #51 · Main CI · Publication workflow

PyPI 1.4.0 · npm 1.4.0

Viajante 1.3.1

Choose a tag to compare

@cursor cursor released this 03 Oct 16:29
4862283

Fixed

  • npm package metadata includes mcpName, required to register the npm transport with MCP Registry. Python and npm versions remain aligned; runtime tools and schemas are unchanged.
  • Release publishing can resume npm and MCP Registry from an existing tag without republishing PyPI. MCP Registry waits for the npm version to become publicly available, and token-free npm publishing removes setup-node's empty auth entry before using OIDC.

Full Changelog: v1.3.0...v1.3.1

Viajante 1.3.0

Choose a tag to compare

@cursor cursor released this 03 Oct 16:29
7732bfb

Added

  • MCP search_hotels accepts up to 8 stays, each with location, dates, and optional adults and rooms. Multi-stay reports carry property_matrix: each property's total per stay, sorted by name, never by price. A null means it was not among that stay's returned offers, not that it is unavailable.
  • Hotel near ({lat, lng} in MCP, --near LAT,LNG in CLI): offers with owned coordinates carry straight-line distance_km to the named point. No point is assumed.
  • Google Hotels evidence: offer sleeps, place_types, class_label, and priced_adults; query-result resolved_place and place_bounds. Vacation-rental chips feed details, allowing bedrooms, beds, and lodging kind to be parsed.
  • Opt-in hotel source skiplagged (MCP source, CLI --source): USD only, at most 10 adults and 9 rooms, no entire_home, never mixed with Google or Booking. Offers carry provider_id; resolved_place identifies the city actually searched when Skiplagged loosely resolves a place name.
  • MCP search_hotel_rooms / CLI viajante hotel-rooms: Skiplagged room rates with provider occupancy_limit, refundable, free_cancellation, and taxes_and_fees, in provider order. Select by hotel id or exact normalized name plus city; no match or several matches returns no_results with returned candidates when available, never a guessed match. Room-rate requests support up to 10 adults and 5 rooms.
  • Offline MCP plan_stay_blocks groups consecutive nights with the same people into stay blocks. split_stay_costs shares each stay only among its occupants by their nights, using a named currency and optional per-person nightly fee. Allocated cents sum exactly; uncovered nights are unallocated_nights. Neither tool fetches prices or converts currency.
  • Additive hotel JSON field applied.not_applied names filters a source cannot apply, including Skiplagged's unsupported free-cancellation search filter. Other additive hotel fields are provider_id, distance_km, report near / property_matrix, and the Google evidence fields above; no hotel JSON keys were renamed.
  • MCP verify_answer: flags amounts, currencies, IATA codes, ISO dates, and links in a draft reply that no search in this process returned.
  • Google rate-limit cooldown: a direct HTTP 429 pauses Google searches on the machine (2 min doubling to 30 min, or a named Retry-After); errors carry rate_limited: true. Identical successful MCP searches within 5 minutes return cached: true.
  • Google Hotels offers carry owned latitude, longitude, and review_count. A named min_rating also fetches the relevance-sorted page on the same multiplexed round-trip.
  • docs/architecture.md: how the request path, fetch modes, hotels, and failure taxonomy fit together.

Changed

  • --fetch auto uses sweep for packaged round-trip and multi-city searches, since only sweep shops the return leg.
  • viajante points is the transfer-table lookup only (mirrors MCP lookup_transfers). Cents-per-point math lives in viajante awards / compare_awards.
  • Explore prices all shortlisted destinations on one multiplexed sweep round-trip.
  • Google Hotels record detection no longer special-cases € (no user-visible change; non-euro totals already parsed).
  • Internal signatures no longer default currency to EUR; every model, source, and parser takes the owned quote currency explicitly.
  • Internal cleanup: one offer-filter bundle, one JSON save path, shared CLI flag helpers (−1.5k lines, JSON unchanged).

Removed

  • The natural-language planner (prompt_plan.py, plan_prompt) and the graded prompt battery (viajante bench --prompts, --holdout, --timeit-sweep, tests/prompts/, LLM judge). The calling agent plans; viajante fetches evidence. get_flights now takes a route spec or trips and rejects prose with ValueError.
  • The looping-agent protocol docs (program.md, bench-history.md, docs/archive/). The offline viajante bench gate stays.

Fixed

  • A data-less Google wrb.fr status 13 envelope is blocked and now records the same cooldown as HTTP 429 for direct sessions only. Google Hotels reports blocked with rate_limited: true, rather than rejected. Shared provider cooldown state lives in ratelimit.py.
  • Skiplagged HTTP 429 is blocked with rate_limited: true, without retries. Its separate skiplagged-rate-limit.json pauses new calls; real calls are paced one second apart.
  • Detail fetch fails fast on google.com/sorry instead of waiting minutes for result cards.
  • viajante hidden-city and MCP search_hidden_city: Skiplagged cards are USD. A named keep that matches no owned card currency is currency_mismatch (owned quote stamped), not silent no_results. Viajante does not convert. Omit currency or pass USD; do not advertise EUR as a Skiplagged quote.
  • MCP search_dates round-trip calendar path: when return_date is set, the calendar sweep uses owned outbound+return pairs. Historical smoke evidence is in docs/smoke-2026-09-17.md.
  • MCP validate_itinerary: never reports feasible=true without owned provenance; incomplete evidence stays unknown/infeasible.

Known limitations

  • Skiplagged quotes are USD and are never converted. A room type's occupancy_limit is the provider's number, not proof that a group fits across several rooms. Its search cannot apply free cancellation; confirm individual room terms.
  • Google hostel prices may be dormitory beds: Google supplies no room type. Check finalists by exact name with search_hotel_rooms and confirm the room on the provider before treating it as private.
  • A data-less status 13 may have another cause; its guessed cooldown can pause Google searches for 2 minutes even without a real rate limit.
  • Google base/tax/fee breakdown (record[6][2][44], unconfirmed) and caller-named exchange rates remain outside this release, pending evidence and a design decision.

Full Changelog: v1.2.1...v1.3.0