fortrip 0.3.0 → 1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FortripEngineering
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,105 +1,216 @@
1
- # fortrip-cli
1
+ # fortrip
2
2
 
3
- Search, price and book Fortrip hotels from the terminal or an AI agent. The
4
- The npm package and the command are both `fortrip`.
3
+ Search hotels, check live room rates and book with a payment link, from the
4
+ terminal or an AI agent. Hotels only for now. The npm package and the command
5
+ are both `fortrip`.
5
6
 
6
7
  ```bash
7
- npx fortrip login # sign in through the browser
8
- npx fortrip search --query Bangkok --check-in 2026-11-10 --check-out 2026-11-12
8
+ npx -y fortrip login
9
+ npx -y fortrip search --query Bangkok --check-in 2026-11-10 --check-out 2026-11-12
9
10
  ```
10
11
 
11
- Requires Node.js 22 or newer. No runtime dependencies.
12
+ ## Install and run
13
+
14
+ Node.js 22 or newer. Run it with `npx`, which needs no install:
15
+
16
+ ```bash
17
+ npx -y fortrip <command>
18
+ ```
19
+
20
+ or install it once and run `fortrip <command>`:
21
+
22
+ ```bash
23
+ npm install --global fortrip
24
+ ```
25
+
26
+ `fortrip --help` lists the commands, `fortrip <command> --help` one command's
27
+ flags, and `fortrip --version` prints the version.
28
+
29
+ Upgrading from 0.3: 1.0 signs in with OAuth, so a 0.3 sign-in is not reused;
30
+ run `fortrip login` once. A `FORTRIP_TOKEN` from 0.3 is no longer accepted.
31
+ `fortrip mcp` replaces the separate `fortrip-mcp` package.
32
+
33
+ ## Sign in
34
+
35
+ ```bash
36
+ fortrip login
37
+ ```
38
+
39
+ `login` prints a code and a link on stderr, opens the link in your browser
40
+ (not with `--no-browser`), and waits until you sign in to Fortrip and approve.
41
+ It then prints your account.
42
+
43
+ An AI agent can't sit in `login`, so any other command that needs a sign-in
44
+ doesn't wait: it exits with code 3 and prints `loginUrl`, `userCode` and
45
+ `expiresInSeconds` as JSON on stderr. The agent shows the link to the user;
46
+ once the user has approved it in the browser, the agent reruns the same
47
+ command, which finishes signing in and carries on. Commands that run in
48
+ parallel share one link. When Fortrip stops accepting the saved sign-in (it
49
+ was revoked, or it expired and couldn't be renewed), the command does the same
50
+ and keeps the old sign-in until the new link is approved.
51
+
52
+ You stay signed in. Access tokens last 24 hours and the CLI renews them
53
+ itself, before they run out; refresh tokens don't expire, so the sign-in lasts
54
+ until you run `fortrip logout`, which revokes this machine's sign-in and
55
+ deletes it (other machines stay signed in). `fortrip whoami` prints the
56
+ signed-in account.
57
+
58
+ The sign-in is saved in `~/.config/fortrip/credentials.json` (`$XDG_CONFIG_HOME`
59
+ is honoured), mode `0600`, per API URL, so a token is only sent to the server
60
+ that issued it.
61
+
62
+ If a new or renewed sign-in can't be saved (the file stays busy or turns out to
63
+ be damaged), `search`, `hotel`, `rates`, `book` and `whoami` still work for that
64
+ run, with the new token. The sign-in is kept in a `credentials.recovered-*.json`
65
+ file next to the credentials file, and the command's JSON output carries a
66
+ `warning` and, when the sign-in could be kept, that file in `recoveryFile`.
67
+ Later commands use it, and the next successful save merges it back. `login`
68
+ doesn't carry on in that case: it exits 1, with `recoveryFile` in the error, and
69
+ the sign-in is kept in that file all the same.
70
+
71
+ If the directory itself can't be written (a read-only home, as in some agent
72
+ sandboxes), `login` exits 1 before it asks you to approve anything, and any
73
+ other command that needs to save a sign-in exits 1 too. The error says to set
74
+ `XDG_CONFIG_HOME` to a directory that can be written, or to set `FORTRIP_TOKEN`.
12
75
 
13
76
  ## Commands
14
77
 
15
78
  | Command | What it does |
16
79
  |---|---|
17
- | `login [--no-browser]` | Device-code login: prints a code, opens `/cli/authorize`, waits for you to approve |
18
- | `logout` | Revokes the saved token on the server and deletes it locally |
19
- | `whoami` | The signed-in account |
20
- | `search` | Hotels with indicative prices |
21
- | `hotel <hotelId> [--with-rooms]` | Static hotel detail |
22
- | `rates` | Live rooms and rates |
23
- | `book` | Order + Stripe payment link |
80
+ | `search` | Find hotels with indicative prices |
81
+ | `hotel <hotelId>` | Static hotel detail: description, policies, facilities and photos |
82
+ | `rates` | Live rooms and rates for up to 15 hotels |
83
+ | `book` | Create an order and get a payment link |
84
+ | `login` | Sign in through the browser (device code) |
85
+ | `logout` | Revoke and forget the saved token |
86
+ | `whoami` | Show the signed-in account |
87
+ | `guide [topic]` | Print the guide for AI agents (Markdown) |
88
+ | `mcp` | Run an MCP server over stdio for local clients, bridged to Fortrip's hosted server |
24
89
 
25
- Run `fortrip --help` for every flag. `search`, `rates` and `book` also accept
26
- `--body '<json>'` or `--body @file.json` with the raw request body; flags
27
- override its fields.
90
+ ```bash
91
+ fortrip rates --hotel <hotelId> --check-in 2026-11-10 --check-out 2026-11-12 --rooms 1 --adults 2
92
+ ```
28
93
 
29
- Output is JSON on stdout. Errors are JSON on stderr, with fixed exit codes:
94
+ `search`, `rates` and `book` also accept `--body '<json>'` or
95
+ `--body @file.json` with the raw request body; flags override its fields.
30
96
 
31
- | Code | Meaning |
32
- |---|---|
33
- | 0 | Success |
34
- | 1 | Other error |
35
- | 2 | Invalid arguments (local or HTTP 400) |
36
- | 3 | Not logged in / token revoked (HTTP 401) |
37
- | 4 | Rate limited (HTTP 429; `retryAfterSeconds` on stderr) |
97
+ `--adults` and `--child-age` are per room, and every room has the same
98
+ occupancy: 2 rooms for 4 adults is `--rooms 2 --adults 2`. `rates` and `book`
99
+ both require `--rooms` and `--adults`.
38
100
 
39
- ## Credentials
101
+ `book` creates an unpaid order and prints a payment link for it. Nothing is
102
+ charged until the person pays on the page the link opens.
40
103
 
41
- - `login` saves the token to `~/.config/fortrip/credentials.json`
42
- (`$XDG_CONFIG_HOME` is honoured), mode `0600`. Tokens are stored per API URL,
43
- so a token is only ever sent to the server that issued it.
44
- - Without a token, any other command starts a device login and exits 3 with
45
- `loginUrl` on stderr instead of waiting. Once that link is approved in the
46
- browser, rerunning the command saves the token and carries on. This is how
47
- AI agents sign in, since they can't sit in `login`.
48
- - `FORTRIP_TOKEN` overrides the saved login (CI, remote sandboxes).
49
- - `FORTRIP_API_URL` overrides the base URL (default `https://fortrip.ai`).
50
- Plain `http` is only accepted for `localhost`.
51
- - `FORTRIP_CURRENCY` sets the default `--currency` for `search` and `rates`
52
- (`CNY` or `USD`; the API defaults to `CNY`). Display only: `book`
53
- charges the currency it returns.
104
+ ## For AI agents
54
105
 
55
- Tokens don't expire; `logout` revokes them.
106
+ ```bash
107
+ npx -y fortrip guide # when to use the CLI, call order, sign-in, what to show before a payment link
108
+ npx -y fortrip guide planning # flexible dates, budgets, split stays, several destinations
109
+ ```
110
+
111
+ Both print Markdown, with `fortrip@latest` replaced by the running version, so
112
+ an agent keeps using the same CLI for the whole conversation. The guide is
113
+ written once in
114
+ [`@fortrip/agent-contract`](https://github.com/FortripEngineering/fortrip/tree/main/packages/contract/guide)
115
+ and compiled into the CLI.
56
116
 
57
- ## Agent skill
117
+ For agents that can run shell commands, the same guide is also a skill:
58
118
 
59
119
  ```bash
60
- npx skills add FortripEngineering/fortrip-cli
120
+ npx skills add FortripEngineering/fortrip --skill fortrip-cli
61
121
  ```
62
122
 
63
- [`skills/fortrip-hotels/SKILL.md`](skills/fortrip-hotels/SKILL.md) only tells
64
- the agent to run `npx -y fortrip@latest skill`, which prints
65
- [`AGENT_GUIDE.md`](AGENT_GUIDE.md): when to use the CLI, the call order, login,
66
- and what to show the user before handing over a payment link. The guide ships
67
- with the package, so a CLI release updates every installed skill. Edit
68
- `AGENT_GUIDE.md`, not `SKILL.md`.
69
-
70
- `fortrip skill planning` prints [`guides/planning.md`](guides/planning.md):
71
- what to ask, how to rank and how to present options for flexible dates,
72
- budgets, split stays and several destinations. Both guides are printed with
73
- `fortrip@latest` replaced by the running version, so an agent keeps using the
74
- same CLI for the whole conversation.
123
+ ## MCP server
124
+
125
+ `fortrip mcp` runs an MCP server on stdio for clients that start local
126
+ servers. It forwards to Fortrip's hosted MCP server, `https://fortrip.ai/api/mcp`,
127
+ with your saved sign-in. Sign in once with `npx -y fortrip login` before you
128
+ add the server to a client.
129
+
130
+ If the client starts the server before you have, the server fails to connect:
131
+ its first request, `initialize`, is answered with a JSON-RPC error (`-32001`)
132
+ whose message says to run `npx -y fortrip login` in a terminal, or to open the
133
+ sign-in link it names and approve it. Clients typically close the connection
134
+ after a failed `initialize`, so sign in (or approve that link), then restart the
135
+ server or reconnect it (`/mcp` in Claude Code). If a sign-in stops working
136
+ later, only the request that hit it fails with the same kind of error, and the
137
+ server keeps running.
138
+
139
+ Claude Desktop (Settings, Developer, Edit Config; on macOS
140
+ `~/Library/Application Support/Claude/claude_desktop_config.json`, on Windows
141
+ `%APPDATA%\Claude\claude_desktop_config.json`) and Cursor (`~/.cursor/mcp.json`,
142
+ or `.cursor/mcp.json` in a project):
143
+
144
+ ```json
145
+ {
146
+ "mcpServers": {
147
+ "fortrip": {
148
+ "command": "npx",
149
+ "args": ["-y", "fortrip", "mcp"]
150
+ }
151
+ }
152
+ }
153
+ ```
75
154
 
76
- ## Development
155
+ Claude Code:
77
156
 
78
157
  ```bash
79
- pnpm install
80
- pnpm dev search --query Bangkok ... # run from source
81
- pnpm test
82
- pnpm typecheck
83
- pnpm build # dist/cli.js
158
+ claude mcp add fortrip -- npx -y fortrip mcp
84
159
  ```
85
160
 
86
- Point at a local Fortrip app with `FORTRIP_API_URL=http://localhost:3000`.
161
+ Codex, with `codex mcp add fortrip -- npx -y fortrip mcp` or in
162
+ `~/.codex/config.toml`:
87
163
 
88
- ## Releasing
164
+ ```toml
165
+ [mcp_servers.fortrip]
166
+ command = "npx"
167
+ args = ["-y", "fortrip", "mcp"]
168
+ ```
169
+
170
+ Clients that support remote MCP servers with OAuth don't need the CLI: add
171
+ `https://fortrip.ai/api/mcp` as a remote server and sign in to Fortrip in the
172
+ browser when the client asks. In Claude Code, that is
173
+ `claude mcp add --transport http fortrip https://fortrip.ai/api/mcp`.
174
+
175
+ ## Environment variables
176
+
177
+ | Variable | Meaning |
178
+ |---|---|
179
+ | `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. |
180
+ | `FORTRIP_API_URL` | The base URL (default `https://fortrip.ai`). Plain `http` is only accepted for `localhost`. |
181
+ | `FORTRIP_CURRENCY` | The default `--currency` for `search` and `rates` (`CNY` or `USD`; the API uses `CNY` when nothing sets one). It only changes how prices are shown: `book` charges the currency it returns. |
89
182
 
90
- Pushing a `v*` tag publishes to npm through
91
- [`.github/workflows/publish.yml`](.github/workflows/publish.yml), which signs
92
- in with npm trusted publishing (no npm token in GitHub).
183
+ ## Output and exit codes
184
+
185
+ Data commands (`search`, `hotel`, `rates`, `book`, `login`, `logout`,
186
+ `whoami`) print JSON on stdout. `guide` prints Markdown, and `fortrip mcp`
187
+ speaks MCP over stdio. Errors are JSON on stderr, with an `error` message, the
188
+ `exitCode` and any details.
189
+
190
+ | Code | Meaning |
191
+ |---|---|
192
+ | 0 | Success |
193
+ | 1 | Other error (`retryable: true` on stderr: worth one retry) |
194
+ | 2 | Invalid arguments (local or HTTP 400) |
195
+ | 3 | Not signed in, or the sign-in wasn't accepted (HTTP 401); `loginUrl` on stderr |
196
+ | 4 | Rate limited (HTTP 429; `retryAfterSeconds` on stderr) |
197
+
198
+ ## Support
199
+
200
+ For changes, cancellations, refunds or other help with a booking, email
201
+ [info@fortrip.ai](mailto:info@fortrip.ai) with the booking's order link
202
+ (`orderUrl`).
203
+
204
+ ## Releasing
93
205
 
94
- 1. Bump the version in a PR and merge it into `main`:
95
- `npm version minor --no-git-tag-version` (or `patch`).
96
- 2. Tag the merged commit on `main` and push the tag:
206
+ Both packages in this repository, `fortrip` and `@fortrip/agent-contract`,
207
+ are released together from a `vX.Y.Z` tag. See
208
+ [Releasing](https://github.com/FortripEngineering/fortrip#releasing) in the
209
+ repository's README.
97
210
 
98
- ```bash
99
- git checkout main && git pull
100
- git tag v0.2.0 && git push origin v0.2.0
101
- ```
211
+ ## License
102
212
 
103
- The workflow refuses a tag that doesn't match `package.json` or isn't on
104
- `main`, then runs typecheck, tests and the build before publishing. Every
105
- installed skill picks up the new guide on its next `npx fortrip@latest skill`.
213
+ The code and documentation in this repository are licensed under the
214
+ [MIT License](https://github.com/FortripEngineering/fortrip/blob/main/LICENSE).
215
+ This license does not grant access to the hosted Fortrip service, hotel
216
+ inventory, or third-party data.