# Fortrip (npm · fortrip)

Search hotels worldwide, compare live room rates, book and pay securely, and cancel bookings.

- Trust score: 83/100 (high trust)
- Change this week: +3
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-11-05

## Components

- remote · `mcp.fortrip.ai`: 39/100, [markdown](https://verifymcp.io/servers/fortripengineering-fortrip/mcp.md), [page](https://verifymcp.io/servers/fortripengineering-fortrip/mcp)
- npm · `fortrip`: 83/100 (this document), [markdown](https://verifymcp.io/servers/fortripengineering-fortrip/fortrip.md), [page](https://verifymcp.io/servers/fortripengineering-fortrip/fortrip)

## Channel facts

- Registry: `npm`
- Package: `fortrip`
- Version: `4.3.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-11-05.

- **Supply Chain Security**: 99/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - No install/post-install scripts declared.
  - 3 of 14 dependencies flagged as unhealthy.
- **Provenance & Transparency**: 97/100
  - Source repository is publicly reachable at the declared URL.
  - Cryptographically verified build provenance (signed, bound to FortripEngineering/fortrip).
  - Clear OSI-approved license (Apache-2.0).
  - Actively maintained (last published 0 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 59/100
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 2698 tokens (~299/item across 9 items; 9 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 40/100
  - Stability observed for 12 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
  - Structured output schemas are declared (89% of tools); any adoption earns full credit.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - All 1 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.
  - An AI judge read all 10 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### How do I install the Fortrip MCP server?

Fortrip runs locally as an npm package, launched with npx -y fortrip. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add fortripengineering-fortrip -- npx -y fortrip
```

### Cursor

```json
{
  "mcpServers": {
    "fortripengineering-fortrip": {
      "command": "npx",
      "args": [
        "-y",
        "fortrip"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "fortripengineering-fortrip": {
      "command": "npx",
      "args": [
        "-y",
        "fortrip"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add fortripengineering-fortrip -- npx -y fortrip
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "fortripengineering-fortrip": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "fortrip"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add fortripengineering-fortrip --command npx --arg -y --arg fortrip
```

### Hermes

```yaml
mcp_servers:
  fortripengineering-fortrip:
    command: "npx"
    args: ["-y", "fortrip"]
```

### Netclaw

```json
{
  "McpServers": {
    "fortripengineering-fortrip": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "fortrip"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add fortripengineering-fortrip -t stdio -c npx -a -y fortrip
```

### Other

```json
{
  "mcpServers": {
    "fortripengineering-fortrip": {
      "command": "npx",
      "args": [
        "-y",
        "fortrip"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-11-04 (score 83, +15)

- [security regression] Tool safety: pass → unverified
- [security regression] Stability: 0.33 → unverified
- [security regression] Known CVEs: pass → unverified
- [security improvement] Malware scan: unverified → pass
- [functional regression] Capabilities: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional regression] Dependency health: 0.93 → unverified
- [functional] First check of Schema quality: unverified
- [functional] Package version: 3.4.0 → 4.2.0
- [functional] Package version: 3.4.0 → 4.1.0
- [functional] Package version: 3.4.0 → 4.0.0
- [functional] Package version: 3.4.0 → 3.5.0

### 2026-11-03 (score 68, −14)

- [security regression] Malware scan: pass → unverified
- [security regression] Known CVEs: pass → unverified
- [functional regression] Schema quality: 2201 → 2557
- [functional regression] Dependency health: 0.93 → unverified
- [functional] Destructive annotations: pass → 100
- [functional] Package version: 3.3.0 → 3.4.0
- [functional] Package version: 3.3.0 → 3.3.1

### 2026-11-01 (score 82, +1)

No change was recorded against any check on this day. Stability & Change Management went from 23 to 27. That category is still filling its 30-day observation window: 7 days of observed history at the previous scan, 8 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-30 (score 81, +1)

No change was recorded against any check on this day. Stability & Change Management went from 17 to 20. That category is still filling its 30-day observation window: 5 days of observed history at the previous scan, 6 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-28 (score 80, +26)

- [security improvement] Malware scan: unverified → pass
- [security improvement] Known CVEs: unverified → pass
- [functional improvement] Dependency health: unverified → 0.93

### 2026-10-27 (score 54, −10)

- [security regression] Known CVEs: pass → unverified
- [security improvement] Malware scan: unverified → pass
- [functional regression] Schema quality: 1896 → 2201
- [functional regression] Dependency health: 0.93 → unverified
- [functional] Schema quality: good → excellent
- [functional] Package version: 3.1.0 → 3.3.0
- [functional] Package version: 3.1.0 → 3.2.0

### 2026-10-26 (score 64, −14)

- [security regression] Malware scan: pass → unverified
- [functional improvement] Stability: unverified → 0.07
- [functional] Package version: 3.0.0 → 3.1.0

### 2026-10-25 (score 78, +15)

- [security improvement] Malware scan: unverified → pass

## MCP tools (9)

### `get_planning_guide` (~70 tokens)

Get hotel planning guide

Returns Fortrip's planning guide for a request that is more than one hotel for fixed dates (flexible dates, a budget, split stays, several destinations, "find me the best"): what to ask the user, which results count as evidence, how to rank and how to present options.

### `search_hotels` (~449 tokens)

Search hotels

Find hotels by destination and/or text, with an indicative per-room-night price when a stay is given. destination is a place_name with its countryCode, a place or locality by placeId from an earlier answer, a point, or a country. A name several places bear answers destination_ambiguous with candidates: ask the user, then search the chosen placeId. text matches hotel names, brands and areas word for word. Indicative prices are estimates and not bookable: get_hotel_offers returns what the user pays. A search too broad to answer is refused with search_too_broad and its localities: pass one back as { kind: "locality", placeId }, never by name. The answer states the scope, the counts and notes; a next page is the cursor and, optionally, limit.

Input parameters:

- `cursor` (string): `nextCursor` from the previous response. A next page is the cursor and, optionally, `limit`; nothing else.
- `destination`: Where to search. A first page needs this or `text`.
- `displayCurrency` (string): Currency to show prices in, USD or CNY. It never changes what is charged: payment is in USD.
- `filters` (object): Filters every hotel in the answer must pass.
- `limit` (integer): Hotels per page, 1 to 50. Default 20.
- `locale` (string): Language for names and text in the response: en or zh.
- `pricing` (string): `indicative` adds an approximate price per hotel and needs a stay; `none` skips prices. Default: indicative with a stay, otherwise none.
- `sort` (string): Result order. `distance` needs a destination, `relevance` needs `text`, `price_asc` and `price_desc` need indicative pricing. Default: relevance with `text`, otherwise distance.
- `stay` (object): Dates and party. Needed for indicative prices. Search uses only the dates when the rooms differ.
- `text` (string): Hotel name, brand or area to match, 1 to 128 characters. A first page needs this or `destination`.

Output parameters:

- `coverage` (object)
- `data` (array)
- `destination`
- `nextCursor`: Pass it back as cursor for the next page; null on the last page.
- `notes` (array)
- `pricing` (object)
- `sort`
- `stay`
- `text`

### `get_hotel` (~118 tokens)

Get hotel details

One hotel's catalogue facts: names, address, location, time zone, check-in and check-out times, the full description, every policy and the amenities, and its rooms with include: "rooms". "Not listed" is not "no". No prices or availability: get_hotel_offers has those.

Input parameters:

- `hotelId` (string, required): hotelId from a search response.
- `include` (string): `rooms` adds the room list.
- `locale` (string): Language for names and text in the response: en or zh.

Output parameters:

- `address` (object)
- `amenities` (object)
- `bookable` (boolean)
- `breakfastServed`
- `checkInTimes` (object)
- `checkOutTimes` (object)
- `contact` (object)
- `deposit` (object)
- `description`
- `hotelId` (string)
- `location`
- `name` (string)
- `names` (object)
- `photos`: Up to 8 hotel photos, the cover first; null when the catalogue lists none.
- `policies` (object)
- `rooms` (object)
- `stars`
- `timeZone`

### `get_hotel_offers` (~307 tokens)

Get live hotel offers

Live, bookable offers for up to 15 hotels and one stay. Every room in stay.rooms must have the same party: for different parties, call once per party. Each offer has the room, the meals included, price.total in USD for the whole stay and every room (what is charged), fees payable at the property, the cancellation terms with times in UTC and the hotel's time zone, the confirmation mode, and an offerId for book_hotel that expires at expiresAt. Hotels with nothing to offer are listed under unavailable with the reason. Up to limitPerHotel offers per hotel, default 10, chosen for a spread of choices in this order while room remains: the cheapest offer, the cheapest that can be cancelled free, the cheapest with breakfast, the cheapest of each other room, then the rest by price; listed cheapest first.

Input parameters:

- `displayCurrency` (string): Currency to show prices in, USD or CNY. It never changes what is charged: payment is in USD.
- `filters` (object): Filters every offer must pass.
- `hotelIds` (array, required): Hotels to price, 1 to 15, no repeats.
- `limitPerHotel` (integer): Offers per hotel, 1 to 20. Default 10.
- `locale` (string): Language for names and text in the response: en or zh.
- `stay` (object, required): Dates and party. One party per call: every room must be the same.

Output parameters:

- `hotels` (array)
- `stay` (object)
- `unavailable` (array)

### `book_hotel` (~266 tokens)

Create hotel order and payment link

Order one offer from get_hotel_offers. The answer is an unpaid order with a payment link: status awaiting_payment, the total, the stay and its terms, and payment.url, a Fortrip page to pay on. Nothing is charged until the order is paid, on that page or with pay_order (or Alipay/WeChat Pay); anyone holding the link can pay. Send the contact and, for each room of the offer, at least one guest. If the price or terms changed since the offer, the answer is offer_changed with every change and a new offer: show the changes and ask the user again before ordering it. Sending the same details again returns the same order. An offer is ordered once: for another order of the stay (another party, or a corrected guest name), get offers again and order the new offer; when it replaces an unpaid order, tell the user to pay only the new link, as the earlier one expires unpaid. To cancel an order, use cancel_order; for changes, or a cancellation cancel_order can't make, the user emails info@fortrip.ai with the order's reference.

Input parameters:

- `contact` (object, required): Who the hotel and the confirmation reach.
- `items` (array, required): The offer to book: exactly one.

Output parameters:

- `cancel` (object): Whether the order can be cancelled now, and for what penalty and refund.
- `createdAt` (string)
- `items` (array)
- `manageUrl` (string)
- `nextStep` (string): What to show and ask before giving a payment.url. Present when the answer holds a non-null payment.url, and only then.
- `orderId` (string)
- `payment` (object)
- `price` (object)
- `reference` (string)
- `status`
- `updatedAt` (string)

### `get_order` (~109 tokens)

Get order

One of the user's orders by orderId: its status, the payment status and, while it awaits payment, payment.url; the stay and its terms; and the hotel's confirmation number once there is one. Check it after the user pays. An order awaiting payment whose payment.url is null had its link unreadable this time: read it again.

Input parameters:

- `locale` (string): Language for names and text in the response: en or zh.
- `orderId` (string, required): The order's orderId.

Output parameters:

- `cancel` (object): Whether the order can be cancelled now, and for what penalty and refund.
- `createdAt` (string)
- `items` (array)
- `manageUrl` (string)
- `nextStep` (string): What to show and ask before giving a payment.url. Present when the answer holds a non-null payment.url, and only then.
- `orderId` (string)
- `payment` (object)
- `price` (object)
- `reference` (string)
- `status`
- `updatedAt` (string)

### `list_orders` (~92 tokens)

List orders

The user's hotel orders, newest first, including those made on the Fortrip website. Pass nextCursor back as cursor for the next page.

Input parameters:

- `cursor` (string): `nextCursor` from the previous page of orders.
- `limit` (integer): Orders per page, 1 to 50. Default 20.
- `locale` (string): Language for names and text in the response: en or zh.

Output parameters:

- `data` (array)
- `nextCursor`: Pass it back as cursor for the next page; null on the last page.
- `nextStep` (string): What to show and ask before giving a payment.url. Present when the answer holds a non-null payment.url, and only then.

### `cancel_order` (~268 tokens)

Cancel order

Cancel one of the user's orders by orderId under its cancellation terms, when its cancel.available is true: the hotel booking is cancelled and cancel.refund, what was paid less cancel.penalty, is refunded. Before you call cancel_order, show the user the order's stay (hotel, dates), cancel.penalty and cancel.refund (amount and currency), then end your reply by asking them to confirm the cancellation, and wait for a clear yes. Pass maximumPenalty as the number in cancel.penalty.amount ("120.00" → 120). Never state a refund the order did not return. If the penalty is now higher than maximumPenalty, the answer is cancellation_changed and nothing changes: read the order again and ask the user again. Answers the order: status cancelling, then cancelled once the hotel cancels and the refund is issued; poll get_order. If the hotel refuses, the order goes back to confirmed with cancel.reason refused. Calling it again for the same order answers the order as it is.

Input parameters:

- `maximumPenalty` (number, required): The penalty the user agreed to, in the order's currency. Pass maximumPenalty as the number in cancel.penalty.amount ("120.00" → 120).
- `orderId` (string, required): The orderId of the order to cancel.

Output parameters:

- `cancel` (object): Whether the order can be cancelled now, and for what penalty and refund.
- `createdAt` (string)
- `items` (array)
- `manageUrl` (string)
- `orderId` (string)
- `payment` (object)
- `price` (object)
- `reference` (string)
- `status`
- `updatedAt` (string)

### `pay_order` (~409 tokens)

Pay order by token or Alipay/WeChat Pay

Pay an order without its link, by shared payment token or Alipay/WeChat Pay (method alipay_wechat_pay). Token: only if payment.handlers isn't empty and you can request one from the user's Link wallet (US and Canadian accounts); never ask the user for one. First show the user the USD total, the stay and every term (meals, cancellation, fees payable at the property), ask them to confirm and wait for a clear yes. Token: request it with config.business_profile and payment.credentialLimits; pass it with price.total. Wallet: pass method, price.total; show payment.wallets (WeChat code as an image if you can, both links); they pay once by either; a code lasts 120 minutes; then the WeChat link opens a new one, or call again. Pay one way only: payment.url or pay_order. On success payment.url stops working; on failure it stays open. Then poll get_order. payment_total_changed: confirm details.total, retry. payment_credential_invalid: new token. service_unavailable: retry. Else payment.url. A token pays one order only.

Input parameters:

- `method` (string): Pay with Alipay or WeChat Pay instead of a token: opens the payment and returns payment.wallets. Exactly one of sharedPaymentToken, payment and method.
- `orderId` (string, required): The orderId of the order to pay.
- `payment` (object): UCP's Complete Checkout payment, in place of sharedPaymentToken: the token as the stripe_payment_token credential of the one selected stripe_payments card instrument. Exactly one of sharedPaymentToke…
- `sharedPaymentToken` (string): The shared payment token (spt_…) the user approved for this order, requested with the order's payment.credentialLimits. Exactly one of sharedPaymentToken, payment and method.
- `total` (object, required): The total the user approved: the order's price.total, exactly as returned.

Output parameters:

- `cancel` (object): Whether the order can be cancelled now, and for what penalty and refund.
- `createdAt` (string)
- `items` (array)
- `manageUrl` (string)
- `orderId` (string)
- `payment` (object)
- `price` (object)
- `reference` (string)
- `status`
- `updatedAt` (string)

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/fortripengineering-fortrip/fortrip#diagnostics

## Score history

- 2026-11-05: 83
- 2026-11-04: 83
- 2026-11-03: 68
- 2026-11-02: 82
- 2026-11-01: 82
- 2026-10-31: 81
- 2026-10-30: 81
- 2026-10-29: 80
- 2026-10-28: 80
- 2026-10-27: 54
- 2026-10-26: 64
- 2026-10-25: 78
- 2026-10-24: 63

## Common questions

### What is the Fortrip MCP server?

Fortrip is an MCP server listed in the public MCP registry as io.github.FortripEngineering/fortrip. Search hotels worldwide, compare live room rates, book and pay securely, and cancel bookings. This page covers its npm package (fortrip).

### Is the Fortrip MCP server safe to use?

Fortrip scores 83 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 5 November 2026. It declares no install or post-install scripts. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the Fortrip MCP server expose?

Fortrip exposes 9 tools: get_planning_guide, search_hotels, get_hotel, get_hotel_offers, book_hotel, and 4 more. Their descriptions and schemas cost roughly 2,088 tokens of context every time the server is loaded.

### Is the Fortrip MCP server still maintained?

Fortrip is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the Fortrip MCP server under?

Fortrip declares the Apache-2.0 licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- npm package: https://www.npmjs.com/package/fortrip
- Socket report: https://socket.dev/npm/package/fortrip
- Repository: https://github.com/FortripEngineering/fortrip
- Website: https://fortrip.ai/
- Changelog RSS feed: https://verifymcp.io/servers/fortripengineering-fortrip/fortrip.xml
- Changelog JSON feed: https://verifymcp.io/servers/fortripengineering-fortrip/fortrip.json
- HTML version of this page: https://verifymcp.io/servers/fortripengineering-fortrip/fortrip
