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 +131 -73
- package/dist/{chunk-53656LB2.js → chunk-26IHFJYT.js} +2223 -569
- package/dist/cli.js +262 -107
- package/dist/{mcp-bridge-LPQBHWLD.js → mcp-bridge-3WLWV2KY.js} +87 -24
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# fortrip
|
|
2
2
|
|
|
3
|
-
Search hotels, check live
|
|
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 --
|
|
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
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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`
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
parallel share one link. When Fortrip
|
|
67
|
-
was revoked, or it expired and couldn't
|
|
68
|
-
and keeps the old sign-in until the new
|
|
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
|
|
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
|
|
84
|
-
`warning` and, when the sign-in could be kept, that file in `recoveryFile
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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>` |
|
|
100
|
-
| `hotels
|
|
101
|
-
| `hotels book` |
|
|
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
|
|
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
|
|
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
|
-
`--
|
|
116
|
-
|
|
117
|
-
`hotels
|
|
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
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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`).
|
|
197
|
-
| `
|
|
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
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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 |
|
|
210
|
-
| 2 | Invalid arguments (local or
|
|
211
|
-
| 3 | Not signed in, or the sign-in wasn't accepted
|
|
212
|
-
| 4 | Rate limited (
|
|
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
|
|
218
|
-
(`orderUrl`).
|
|
276
|
+
[info@fortrip.ai](mailto:info@fortrip.ai) with the order's reference or link.
|
|
219
277
|
|
|
220
278
|
## Releasing
|
|
221
279
|
|