fortrip 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # fortrip
2
2
 
3
- Search hotels, check live room rates and book with a payment link, from the
3
+ Search hotels, check live offers and order one with a payment link, from the
4
4
  terminal or an AI agent. Hotels only for now. The npm package and the command
5
- are both `fortrip`.
5
+ are both `fortrip`; they talk to Fortrip API v1, `https://api.fortrip.ai/v1`.
6
6
 
7
7
  ```bash
8
8
  npx -y fortrip login
9
- npx -y fortrip hotels search --query Bangkok --check-in 2026-11-10 --check-out 2026-11-12
9
+ npx -y fortrip hotels search --place-name Bangkok --country TH --check-in 2026-11-10 --check-out 2026-11-12 --room 2
10
10
  ```
11
11
 
12
12
  ## Install and run
@@ -27,26 +27,64 @@ npm install --global fortrip
27
27
  commands, `fortrip <command> --help` one command's flags, and
28
28
  `fortrip --version` prints the version.
29
29
 
30
- Upgrading from 0.3: 1.0 signs in with OAuth, so a 0.3 sign-in is not reused;
31
- run `fortrip login` once. A `FORTRIP_TOKEN` from 0.3 is no longer accepted.
32
- `fortrip mcp` replaces the separate `fortrip-mcp` package.
33
-
34
- ## Upgrading from 1.x
35
-
36
- 2.0 puts the hotel commands under `fortrip hotels`, with the same flags and
37
- arguments:
38
-
39
- | 1.x | 2.0 |
40
- |---|---|
41
- | `search` | `hotels search` |
42
- | `hotel <hotelId>` | `hotels get <hotelId>` |
43
- | `rates` | `hotels rates` |
44
- | `book` | `hotels book` |
45
-
46
- Two MCP tools are renamed: `get_rates` is now `get_hotel_rates` and
47
- `create_booking` is now `book_hotel`. Sign-in is unchanged. `fortrip mcp` now
48
- also starts before you sign in: it lists its tools, and the first tool call
49
- answers with the sign-in link. 2.0 is licensed under Apache 2.0 instead of MIT.
30
+ ## Upgrading from 2.x
31
+
32
+ 3.0 moves the CLI to Fortrip API v1. A 2.x CLI and the 2.x MCP server stop
33
+ working when 3.0 is released, so upgrade the CLI and, if you added it, the
34
+ hosted MCP server's address (see [MCP server](#mcp-server)).
35
+
36
+ - **Sign in again.** The CLI keeps one sign-in per API URL. 2.x saved yours
37
+ under `https://fortrip.ai`; 3.0's API is `https://api.fortrip.ai`, so run
38
+ `fortrip login` once. The old sign-in is not revoked and is left in the file;
39
+ `fortrip logout` removes only the new one.
40
+ - **`hotels rates` is now `hotels offers`.** It prices up to 15 hotels with
41
+ live, bookable offers. `hotels book` orders an offer by its `offerId`
42
+ (`--offer`), and the guests are given per room (`--guest room:first:last`),
43
+ instead of by room and rate plan. `hotels search`, `hotels get`, `login`,
44
+ `logout`, `whoami`, `guide` and `mcp` keep their names; `orders get` and
45
+ `orders list` are new.
46
+ - **Flags changed with the API.** Run `fortrip <command> --help` for the flags
47
+ of 3.0; these are the 2.x ones that moved.
48
+ - Search: `--query` and `--city-code` are replaced by `--place-name` with its
49
+ `--country` (or `--place`, `--locality`, `--point`, `--country-only`);
50
+ `--text` matches a hotel name, brand or area. `--near` is
51
+ `--point lat,lng` with `--radius-meters` (meters, where `--near` took km). `--star-min` and `--star-max`
52
+ are `--stars-min` and `--stars-max`, `--facility` is `--amenity` and
53
+ `--price-max` is `--price-max-per-room-night`. `--price-min` and the short `-q` are gone.
54
+ - Paging: `--page` and `--page-size` are not renamed but replaced. Results
55
+ are paged with a cursor: pass the `nextCursor` of the previous page to
56
+ `--cursor`, and set the page size with `--limit`. There is no page number.
57
+ - Rooms: `--rooms`, `--adults` and `--child-age` are replaced by
58
+ `--room <adults[:age,…]>`, once per room, in `hotels search` and
59
+ `hotels offers`. `hotels book` no longer takes the stay at all: the offer
60
+ carries it.
61
+ - `hotels get`: `--with-rooms` is `--rooms`.
62
+ - `hotels offers` (was `hotels rates`): `--board` is `--require-breakfast`,
63
+ `--free-cancellation` is `--require-free-cancellation`, and `--max-rooms`
64
+ (rooms per hotel) is `--limit-per-hotel` (offers per hotel, 5 by default).
65
+ `--nationality` and `--include-unbookable` are gone.
66
+ - `hotels book`: `--hotel`, `--room-id` and `--rate-plan` are replaced by
67
+ `--offer`, the `offerId` from `hotels offers`. `--guest "First Last:2"` is
68
+ `--guest 2:First:Last` (room, first name, last name). `--contact-name` is
69
+ `--first-name` and `--last-name`, `--contact-phone` is `--phone` and
70
+ `--contact-email` is `--email`.
71
+ - `--currency` is `--display-currency`, which only changes the currency
72
+ prices are shown in: orders are paid in USD.
73
+ - Ids are strings (`htl_…`, `off_…`, `ord_…`, `plc_…`) that you pass back as
74
+ they were returned.
75
+ - **New output.** A result is compact text by default, written for people and
76
+ for models; `--json` prints the API's JSON instead (see
77
+ [Output and exit codes](#output-and-exit-codes)). 2.x printed JSON.
78
+ - **New environment names.** `FORTRIP_CURRENCY` is now
79
+ `FORTRIP_DISPLAY_CURRENCY`, and the default `FORTRIP_API_URL` is
80
+ `https://api.fortrip.ai`. `FORTRIP_MCP_URL` is new. See
81
+ [Environment variables](#environment-variables).
82
+ - **MCP.** The hosted MCP server is `https://mcp.fortrip.ai/`; its address on
83
+ `fortrip.ai` is retired. `get_hotel_rates` is now `get_hotel_offers`, and
84
+ `get_order` and `list_orders` are new.
85
+
86
+ Commands of 1.x and earlier that were renamed (`hotel`, `rates`) are answered
87
+ with the command to type instead.
50
88
 
51
89
  ## Sign in
52
90
 
@@ -60,12 +98,13 @@ It then prints your account.
60
98
 
61
99
  An AI agent can't sit in `login`, so any other command that needs a sign-in
62
100
  doesn't wait: it exits with code 3 and prints `loginUrl`, `userCode` and
63
- `expiresInSeconds` as JSON on stderr. The agent shows the link to the user;
64
- once the user has approved it in the browser, the agent reruns the same
65
- command, which finishes signing in and carries on. Commands that run in
66
- parallel share one link. When Fortrip stops accepting the saved sign-in (it
67
- was revoked, or it expired and couldn't be renewed), the command does the same
68
- and keeps the old sign-in until the new link is approved.
101
+ `expiresInSeconds` on stderr (as `name: value` lines, or beside the error with
102
+ `--json`). The agent shows the link to the user; once the user has approved it
103
+ in the browser, the agent reruns the same command, which finishes signing in
104
+ and carries on. Commands that run in parallel share one link. When Fortrip
105
+ stops accepting the saved sign-in (it was revoked, or it expired and couldn't
106
+ be renewed), the command does the same and keeps the old sign-in until the new
107
+ link is approved.
69
108
 
70
109
  You stay signed in. Access tokens last 24 hours and the CLI renews them
71
110
  itself, before they run out; refresh tokens don't expire, so the sign-in lasts
@@ -78,13 +117,14 @@ is honoured), mode `0600`, per API URL, so a token is only sent to the server
78
117
  that issued it.
79
118
 
80
119
  If a new or renewed sign-in can't be saved (the file stays busy or turns out to
81
- be damaged), the `hotels` commands and `whoami` still work for that run, with
82
- the new token. The sign-in is kept in a `credentials.recovered-*.json`
83
- file next to the credentials file, and the command's JSON output carries a
84
- `warning` and, when the sign-in could be kept, that file in `recoveryFile`.
85
- Later commands use it, and the next successful save merges it back. `login`
86
- doesn't carry on in that case: it exits 1, with `recoveryFile` in the error, and
87
- the sign-in is kept in that file all the same.
120
+ be damaged), the `hotels` and `orders` commands and `whoami` still work for that
121
+ run, with the new token. The sign-in is kept in a `credentials.recovered-*.json`
122
+ file next to the credentials file, and the command's output carries a
123
+ `warning` and, when the sign-in could be kept, that file in `recoveryFile`
124
+ (as lines after the result, or as fields of the JSON with `--json`). Later
125
+ commands use it, and the next successful save merges it back. `login` doesn't
126
+ carry on in that case: it exits 1, with `recoveryFile` in the error, and the
127
+ sign-in is kept in that file all the same.
88
128
 
89
129
  If the directory itself can't be written (a read-only home, as in some agent
90
130
  sandboxes), `login` exits 1 before it asks you to approve anything, and any
@@ -95,10 +135,12 @@ other command that needs to save a sign-in exits 1 too. The error says to set
95
135
 
96
136
  | Command | What it does |
97
137
  |---|---|
98
- | `hotels search` | Find hotels with indicative prices |
99
- | `hotels get <hotelId>` | Static hotel detail: description, policies, facilities and photos |
100
- | `hotels rates` | Live rooms and rates for up to 15 hotels |
101
- | `hotels book` | Create an order and get a payment link |
138
+ | `hotels search` | Find hotels in a place, near a point or by name, with indicative prices |
139
+ | `hotels get <hotelId>` | Hotel details: description, policies, amenities and rooms |
140
+ | `hotels offers` | Live bookable offers for up to 15 hotels |
141
+ | `hotels book` | Order an offer: an unpaid order with a payment link |
142
+ | `orders get <orderId>` | Show an order and its status |
143
+ | `orders list` | List your orders, newest first |
102
144
  | `login` | Sign in through the browser (device code) |
103
145
  | `logout` | Revoke and forget the saved token |
104
146
  | `whoami` | Show the signed-in account |
@@ -106,18 +148,22 @@ other command that needs to save a sign-in exits 1 too. The error says to set
106
148
  | `mcp` | Run an MCP server over stdio for local clients, bridged to Fortrip's hosted server |
107
149
 
108
150
  ```bash
109
- fortrip hotels rates --hotel <hotelId> --check-in 2026-11-10 --check-out 2026-11-12 --rooms 1 --adults 2
151
+ fortrip hotels search --place-name Tokyo --country JP --check-in 2026-11-10 --check-out 2026-11-12 --room 2
152
+ fortrip hotels offers --hotel <hotelId> --check-in 2026-11-10 --check-out 2026-11-12 --room 2 --room 2
110
153
  ```
111
154
 
112
- `hotels search`, `hotels rates` and `hotels book` also accept `--body '<json>'`
155
+ `hotels search`, `hotels offers` and `hotels book` also accept `--body '<json>'`
113
156
  or `--body @file.json` with the raw request body; flags override its fields.
114
157
 
115
- `--adults` and `--child-age` are per room, and every room has the same
116
- occupancy: 2 rooms for 4 adults is `--rooms 2 --adults 2`. `hotels rates` and
117
- `hotels book` both require `--rooms` and `--adults`.
158
+ `--room` gives one room's party, as `adults` or `adults:age,age` with each
159
+ child's age, and is repeated for each room: two rooms of 2 adults, one with a
160
+ child of 6, is `--room 2 --room 2:6`. `hotels search` accepts rooms that
161
+ differ; `hotels offers` takes one party per call, so every room must be the
162
+ same.
118
163
 
119
164
  `hotels book` creates an unpaid order and prints a payment link for it.
120
- Nothing is charged until the person pays on the page the link opens.
165
+ Nothing is charged until the person pays on the page the link opens. Orders
166
+ are paid in USD whatever `--display-currency` shows.
121
167
 
122
168
  ## For AI agents
123
169
 
@@ -140,17 +186,27 @@ npx skills add FortripEngineering/fortrip --skill fortrip-cli
140
186
 
141
187
  ## MCP server
142
188
 
143
- `fortrip mcp` runs an MCP server on stdio for clients that start local
144
- servers. It forwards to Fortrip's hosted MCP server, `https://fortrip.ai/api/mcp`,
145
- with your saved sign-in.
189
+ Fortrip's hosted MCP server is `https://mcp.fortrip.ai/`. It has seven tools:
190
+ `get_planning_guide`, `search_hotels`, `get_hotel`, `get_hotel_offers`,
191
+ `book_hotel`, `get_order` and `list_orders`.
146
192
 
147
- You can add the server to a client before you sign in: signed out, it still
148
- starts and lists its tools. The first tool call is then answered with a
149
- JSON-RPC error (`-32001`) whose message says to run `npx -y fortrip login` in a
150
- terminal, or to open the sign-in link it names and approve it. Once you have,
151
- the next tool call works, with no restart. If a sign-in stops working later,
152
- only the request that hit it fails with the same kind of error, and the server
153
- keeps running.
193
+ Clients that support remote MCP servers with OAuth don't need the CLI: add
194
+ `https://mcp.fortrip.ai/` as a remote server and sign in to Fortrip in the
195
+ browser when the client asks. In Claude Code, that is
196
+ `claude mcp add --transport http fortrip https://mcp.fortrip.ai/`.
197
+
198
+ Clients that start local servers can run the CLI as a bridge. `fortrip mcp`
199
+ runs an MCP server on stdio that forwards to the hosted server with your saved
200
+ sign-in.
201
+
202
+ You can add the bridge to a client before you sign in: signed out, it still
203
+ starts and lists its tools. A tool call is then answered with a tool error
204
+ (`isError: true`, code `unauthenticated`) whose message says to run
205
+ `npx -y fortrip login` in a terminal, or to open the sign-in link it names and
206
+ approve it. Once you have, the next tool call works, with no restart. If a
207
+ sign-in stops working later, only the request that hit it fails, the same way
208
+ for a tool call; any other request that hits a sign-in problem gets the
209
+ JSON-RPC error `-32001` instead. The server keeps running.
154
210
 
155
211
  Claude Desktop (Settings, Developer, Edit Config; on macOS
156
212
  `~/Library/Application Support/Claude/claude_desktop_config.json`, on Windows
@@ -183,39 +239,41 @@ command = "npx"
183
239
  args = ["-y", "fortrip", "mcp"]
184
240
  ```
185
241
 
186
- Clients that support remote MCP servers with OAuth don't need the CLI: add
187
- `https://fortrip.ai/api/mcp` as a remote server and sign in to Fortrip in the
188
- browser when the client asks. In Claude Code, that is
189
- `claude mcp add --transport http fortrip https://fortrip.ai/api/mcp`.
190
-
191
242
  ## Environment variables
192
243
 
193
244
  | Variable | Meaning |
194
245
  |---|---|
195
246
  | `FORTRIP_TOKEN` | An access token, used instead of the saved sign-in. It lasts at most 24 hours, so it suits one sandbox session or one CI run, not standing CI. It isn't tied to a server: it is sent to whatever `FORTRIP_API_URL` points at. If Fortrip doesn't accept it, or it contains a line break or another character that can't be sent in a header, commands exit 3 with `tokenSource: "FORTRIP_TOKEN"` and no `loginUrl`; the error never repeats the token. |
196
- | `FORTRIP_API_URL` | The base URL (default `https://fortrip.ai`). Plain `http` is only accepted for `localhost`. |
197
- | `FORTRIP_CURRENCY` | The default `--currency` for `hotels search` and `hotels rates` (`CNY` or `USD`; the API uses `CNY` when nothing sets one). It only changes how prices are shown: `hotels book` charges the currency it returns. |
247
+ | `FORTRIP_API_URL` | The API's base URL (default `https://api.fortrip.ai`). It must be `https`, except for `localhost`, `127.0.0.1` and `[::1]`, which may use plain `http`. It may end in a path prefix (`http://localhost:3000/api/public`), which every request path follows; a query or fragment is dropped. |
248
+ | `FORTRIP_MCP_URL` | The MCP server `fortrip mcp` bridges to (default `https://mcp.fortrip.ai/`), under the same URL rule. Your sign-in is sent to it, so it must be the MCP server of the API you use: on the origin of `FORTRIP_API_URL`, except that the default API goes with the default MCP server, `api.fortrip.ai` and `mcp.fortrip.ai`. When you set `FORTRIP_API_URL` to a local or preview API, set `FORTRIP_MCP_URL` too; `fortrip mcp` exits 2 and says so when you don't. |
249
+ | `FORTRIP_DISPLAY_CURRENCY` | The default `--display-currency` for `hotels search` and `hotels offers` (`USD` or `CNY`). It only changes the currency prices are shown in: orders are paid in USD. |
198
250
 
199
251
  ## Output and exit codes
200
252
 
201
- Data commands (the `hotels` commands, `login`, `logout` and `whoami`) print
202
- JSON on stdout. `guide` prints Markdown, and `fortrip mcp`
203
- speaks MCP over stdio. Errors are JSON on stderr, with an `error` message, the
204
- `exitCode` and any details.
253
+ A command prints its result as compact text on stdout, the same text the MCP
254
+ tools return. With `--json` (anywhere before `--`) it prints the API's JSON
255
+ instead, on one line. `guide` prints Markdown and `fortrip mcp` speaks MCP over
256
+ stdio.
257
+
258
+ Errors go to stderr, as text, or with `--json` as one line of JSON:
259
+ `{ "error": { "code", "message", "retryable", "requestId", … } }`, Fortrip's
260
+ error envelope, with the CLI's own facts (`loginUrl`, `tokenSource`, `warning`)
261
+ beside it. An error the CLI makes itself, such as a request it refuses to send
262
+ before it asks Fortrip, has an envelope of the same shape, with a `requestId`
263
+ that starts with `local_`.
205
264
 
206
265
  | Code | Meaning |
207
266
  |---|---|
208
267
  | 0 | Success |
209
- | 1 | Other error (`retryable: true` on stderr: worth one retry) |
210
- | 2 | Invalid arguments (local or HTTP 400) |
211
- | 3 | Not signed in, or the sign-in wasn't accepted (HTTP 401); `loginUrl` on stderr |
212
- | 4 | Rate limited (HTTP 429; `retryAfterSeconds` on stderr) |
268
+ | 1 | Any other error, including the answers of the API that aren't mistakes in the request, such as `destination_ambiguous` or `offer_changed` (`retryable` says whether it is worth one retry) |
269
+ | 2 | Invalid arguments (local, or the API's `invalid_request`) |
270
+ | 3 | Not signed in, or the sign-in wasn't accepted; `loginUrl` on stderr |
271
+ | 4 | Rate limited (`retryAfterSeconds` on stderr) |
213
272
 
214
273
  ## Support
215
274
 
216
275
  For changes, cancellations, refunds or other help with a booking, email
217
- [info@fortrip.ai](mailto:info@fortrip.ai) with the booking's order link
218
- (`orderUrl`).
276
+ [info@fortrip.ai](mailto:info@fortrip.ai) with the order's reference or link.
219
277
 
220
278
  ## Releasing
221
279