{
  "markdown": "# @voyagier/cli\n\n[![CI](https://github.com/Voyagier-Travel/voyagier-cli/actions/workflows/tests-and-coverage.yaml/badge.svg?branch=main)](https://github.com/Voyagier-Travel/voyagier-cli/actions/workflows/tests-and-coverage.yaml)\n[![npm version](https://img.shields.io/npm/v/%40voyagier%2Fcli)](https://www.npmjs.com/package/@voyagier/cli)\n[![node](https://img.shields.io/node/v/%40voyagier%2Fcli)](https://www.npmjs.com/package/@voyagier/cli)\n[![MCP](https://img.shields.io/badge/MCP-stdio%20server-black)](https://github.com/Voyagier-Travel/voyagier-cli#mcp-server)\n[![license](https://img.shields.io/npm/l/%40voyagier%2Fcli)](https://github.com/Voyagier-Travel/voyagier-cli/blob/main/LICENSE)\n\nSearch flights, book activities, manage trip plans — from your terminal. Everything syncs to [voyagier.com](https://voyagier.com).\n\n```bash\nnpm install -g voyagier        # or the canonical package: @voyagier/cli\nvoyagier auth set-token <your-token>\nvoyagier doctor   # confirm auth + schema reachability\n```\n\n`voyagier` is a convenience alias that tracks the latest compatible `@voyagier/cli` release (currently `^3`). Pinning an exact version? Use the canonical package: `npm install -g @voyagier/cli@<version>`.\n\nNo install permissions (sandboxed agent, CI)? Every command works zero-install via `npx`:\n\n```bash\nVOYAGIER_TOKEN=<your-token> npx @voyagier/cli doctor --json\n```\n\n## Quick Start\n\nA trip plan is a **goal graph**: the plan ships with goals (flights, hotel, dates, destination, travellers) and you compose the trip by searching against those goals and selecting options. Searches are **asynchronous** — a search creates a selection, and options arrive shortly after, so you poll for them.\n\n```bash\n# 1) Resolve a client (idempotent by email)\nvoyagier clients upsert --email \"smith@example.com\" --name \"Smith Family\" \\\n  --type Individual --json\n\n# 2) Scaffold a plan (creates the plan + the goal graph its template names;\n#    optionally adds the party if you pass --travellers)\nvoyagier plan-trip --client \"Smith Family\" --title \"Smith — Tokyo\" --json\n# --template picks the shape: RoundTripFlightAndHotel (default) | RoundTripFlight\n#   | OneWayFlight | OneWayFlightAndHotel | HotelOnly | Blank\n# Returns a scaffold summary: { ok, tripPlanId, title, travellerIds, scaffolded,\n# template, goals, note, url, nextSteps } — nextSteps are the compose commands.\n\n# 3) Add a traveller\nvoyagier travellers add --plan <PLAN_ID> --first John --last Smith \\\n  --type Adult --json\n\n# 4) Search flights → poll for options → select\nvoyagier search flights --plan <PLAN_ID> --from JFK --to NRT \\\n  --date 2026-09-15 --return 2026-09-22 --json\n# Returns a selectionId. Options are fetched asynchronously:\nvoyagier selection-options <SELECTION_ID> --wait --json\nvoyagier select --selection-id <SELECTION_ID> --option-id <OPTION_ID> --wait --json\n\n# 5) Search a hotel → poll → select\nvoyagier search hotels --plan <PLAN_ID> --location Tokyo \\\n  --checkin 2026-09-15 --checkout 2026-09-22 --json\nvoyagier selection-options <SELECTION_ID> --wait --json\nvoyagier select --selection-id <SELECTION_ID> --option-id <OPTION_ID> --json\n\n# 6) Inspect readiness at any time — one call: what's blocked, what's next\nvoyagier plan-status <PLAN_ID> --json\n\n# 7) Pre-flight (dry-run: blockers + chargeable subtotal), then checkout (price gate required)\nvoyagier book <PLAN_ID> --dry-run --json                   # preview: blockers + chargeable subtotal; no gate needed\nvoyagier book <PLAN_ID> --expect-total <subtotal> --json   # checkout only at that exact price\nvoyagier book <PLAN_ID> --validate --expect-total <subtotal> --json  # strict: also abort if ANY item is non-bookable\n```\n\n## What's Bookable\n\n| Selection | Bookable? | Source |\n|-----------|-----------|--------|\n| Activity | ✅ per slot | Activity supplier |\n| Hotel | ✅ via room-rate item | Accommodation supplier / advisor inventory (pick hotel → pick room; baseline rate auto-carted; rate-less listings stay display-only) |\n| Flight | ✅ via Fare & Cabin item | Air supplier / GDS (fare-level item carted once all legs are picked; defaults to Economy) |\n\nThe cart materializes only bookable, fare/room-level options — the per-item `isBookable` flag is the live truth. Always run `voyagier book <planId> --dry-run` first for pre-flight checks (blockers + chargeable subtotal, no gate needed); `--validate` is a strictness modifier on the real booking that aborts if any item is non-bookable. A real checkout requires a **price gate** (`--expect-total` or `--max-total`) against the chargeable subtotal, and the checkout is always pinned to that gated set via `itemIds` — `--types` / `--only-bookable` narrow it server-side. Note: unpaid (Pending) checkout sessions are not visible to the CLI, so never retry a successful `book`. Cart items sourced from live-rate suppliers may report `source: \"OTHER\"` — that's normal, not an error.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `voyagier doctor` | Self-check: auth, schema, reachability, state, version |\n| `voyagier clients` | Advisor CRM (`list`, `get`, `create`, `update`, `archive`, `upsert`) |\n| `voyagier destinations` | `search <query>` — resolve freeform destination text to structured candidates (id, type, country, region) |\n| `voyagier plans` | `create`, `list`, `get`, `summary`, `delete`; `plans goals` for the goal graph + readiness; `plans bookable` for pre-flight |\n| `voyagier plan-trip` | Scaffold a plan (plan + the goal graph its `--template` names; adds the party only if `--travellers` is given) and print compose next-steps. `--destination-id <id>` from `destinations search` pins the destination; `--destination <name>` is the freeform fallback |\n| `voyagier plan-status <planId>` | One-shot readiness: BOOKED / READY_TO_BOOK / BLOCKED / IN_PROGRESS, ordered blockers, runnable next steps |\n| `voyagier travellers` | Add, list, update, remove travellers |\n| `voyagier traveller-groups` | Manage traveller groups (list, create, update, delete, members) |\n| `voyagier traveller-choices` | Inspect per-traveller selection choices for a plan |\n| `voyagier search` | Flights, hotels, activities, airports — creates a selection; options arrive async |\n| `voyagier selection-options <selectionId>` | Read / poll a selection's options (`--wait` to poll until ready) |\n| `voyagier select` | Choose an option (`--selection-id <id> --option-id <id>`, or by index; `--wait` to settle readiness after the pick) |\n| `voyagier itinerary` | Computed itinerary (sourced from `tripPlanEvents`) |\n| `voyagier listings` | Advisor inventory listings — recent change events, add to selection |\n| `voyagier places` | Search / get / attach / list / highlight (external places + internal catalog) |\n| `voyagier cart` | View cart with by-goal grouping and per-item bookability |\n| `voyagier quote` | Offer snapshot: itemized bookables + the exact total a gated `book` will enforce (`--json` includes the acceptance command) |\n| `voyagier send` | Email the client an invite link to the live trip (self-serve close; requires confirmation / `--yes`) |\n| `voyagier book` | Stripe checkout gated by `--expect-total` / `--max-total`; `--validate`, server-side `--only-bookable` / `--types`, `--rebook` |\n| `voyagier bookings` | View booking records |\n| `voyagier whoami` | Identity + profile (live-verifies the token; `--cached` for offline reads) |\n| `voyagier auth` | Manage PAT / API URL |\n| `voyagier agent-docs` | Print full AI agent integration reference |\n\nMost data-bearing commands accept `--json` for structured output (notable exceptions: `telemetry`, several `auth` subcommands). Use `--plan <id>` on `select` to prevent cross-plan state corruption when running parallel workflows.\n\n## For AI Agents\n\n```bash\nvoyagier agent-docs    # full reference (AGENT.md)\nnpx @voyagier/cli agent-docs   # zero-install variant\n```\n\nOr read [AGENT.md](./AGENT.md) directly. It covers the goal-graph compose model, async option fetch, per-command JSON shapes, the error code table, and the bookability matrix.\n\n## Connect an AI agent\n\nVoyagier runs a hosted MCP server at `https://mcp.voyagier.com/api/mcp`. It is the recommended way for AI agents and assistants to use Voyagier: the client connects to it over HTTP with your Personal Access Token and gets the whole tool surface, with no local install to manage. The CLI itself remains the tool for command-line workflows, scripting, and CI.\n\n`voyagier mcp install <client>` sets this up in one step:\n\n```bash\nvoyagier mcp install claude-code      # writes ./.mcp.json (--global writes ~/.claude.json)\nvoyagier mcp install cursor           # writes ~/.cursor/mcp.json (--project writes ./.cursor/mcp.json)\nvoyagier mcp install claude-desktop   # writes claude_desktop_config.json\n```\n\nIt uses your saved token (`voyagier login`), merges a `voyagier` entry into the client's existing config, and leaves every other server in that file untouched. Pass `--dry-run` to see the resolved path and the exact entry before anything is written, or `--token <pat>` to install a specific token. The token is masked in all output and is only ever written into the config file. Restart the client afterwards to pick up the change.\n\nClaude Desktop's config format describes stdio servers only, so that client is pointed at the CLI's local server (`voyagier mcp`) instead. Voyagier can also be added through the remote connectors section of the app settings, which uses the hosted endpoint directly.\n\n## MCP server\n\nThe CLI ships an [MCP](https://modelcontextprotocol.io) stdio server that exposes the agent surface as tools, for hosts that speak the Model Context Protocol (Claude Desktop, Cursor, etc.):\n\n```bash\nvoyagier mcp          # run the stdio server (JSON-RPC on stdout)\n```\n\nIt's a thin adapter: each tool call self-spawns the CLI as a subprocess with `--json` (the one exception is `agent_docs`, which runs without it), so the tools inherit the CLI's uniform error codes and price-gated checkout — zero behaviour drift. The MCP layer normalises every result into ONE canonical envelope: on success `{ ok: true, data: <object>, planContext? }` (agent_docs markdown arrives as `data.content`), and on failure `{ ok: false, error: { code, message, details? } }` with `isError: true`. Authentication flows through the environment (`VOYAGIER_TOKEN` / `VOYAGIER_API_URL`); the MCP layer never sees your token.\n\n**Claude Desktop** (`claude_desktop_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"voyagier\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@voyagier/cli\", \"mcp\"],\n      \"env\": { \"VOYAGIER_TOKEN\": \"voy_pat_xxxxx\" }\n    }\n  }\n}\n```\n\n**Cursor** (`.cursor/mcp.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"voyagier\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@voyagier/cli\", \"mcp\"],\n      \"env\": { \"VOYAGIER_TOKEN\": \"voy_pat_xxxxx\" }\n    }\n  }\n}\n```\n\n### Tools\n\n| Tool | Maps to | Notes |\n|------|---------|-------|\n| `doctor` | `doctor` | Health check: auth, schema, state, version. |\n| `clients_list` | `clients list` | Roster of CRM clients; `page`/`limit` page through it. |\n| `client_create` | `clients upsert` | Idempotent by email; a plan needs a client. |\n| `plans_list` | `plans list` | Owned + shared plans in one list, each tagged `relationship` `owner`/`shared`; the plan-discovery entry point. `relationship`/`active`/`page`/`limit` filter and page it. |\n| `search_destinations` | `destinations search` | Freeform text → ranked structured destinations; run before `plan_trip`. |\n| `plan_trip` | `plan-trip` | Scaffold a plan + goal graph from a `template`; returns `nextSteps`. `travel_destination_id` (from `search_destinations`) is preferred over the freeform `destination`. |\n| `travellers_add` | `travellers add` | Adds the whole party in one call; required before search. |\n| `search_flights` | `search flights` | Async — `optionCount 0` means poll options. |\n| `search_hotels` | `search hotels` | Prices are stay totals, not nightly. |\n| `search_activities` | `search activities` | Bookable per slot. |\n| `get_selection_options` | `selection-options` | `wait` (default true) polls the async fetch to completion. |\n| `refresh_options` | `refresh-options` | Re-fetch a selection's options; `force` after a fetch error. |\n| `select_option` | `select` | Explicit-id mode; `wait` (default true) settles readiness. |\n| `choices_view` | `choices-view` | Flat participant-choice view; source of room-slot ids. |\n| `choose_room_slot` | `choose-room-slot` | Upsert a room/rate participant choice. |\n| `plan_status` | `plan-status` | One-call \"what's left before booking?\". |\n| `quote` | `quote` | Advisor offer snapshot + acceptance block. |\n| `book_dry_run` | `book --dry-run` | Chargeable subtotal + blockers; no gate needed. |\n| `book` | `book` | **Requires a price gate** — `expect_total_cents` (integer cents, preferred) or `expect_total` (dollars), or `max_total` alone as a cap; fails closed with `PRICE_CHANGED`. |\n| `booking_status` | `book --status` | Post-payment confirmation lookup. |\n| `agent_docs` | `agent-docs` | The full agent reference as markdown. |\n\n> **Deprecated aliases.** `create_client` and `add_traveller` remain registered as deprecated aliases of `client_create` and `travellers_add` (same behaviour) for one release. Prefer the canonical names, which align with the Voyagier platform's first-party MCP tool registry.\n>\n> **`send` is intentionally excluded from the MCP surface.** `voyagier send` emails a real client an invite link and is not idempotent — every call re-emails. That side effect is too consequential to expose behind an autonomous tool call; use the CLI directly (`voyagier send <planId> --yes`) when you mean it. The MCP close path is `quote` → `book`.\n>\n> **`book` cannot be retried safely.** Unpaid Stripe sessions are invisible to the pre-flight, so a retry mints a duplicate payable link. Treat a successful `book` as terminal.\n\n## Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `VOYAGIER_TOKEN` | Personal access token (overrides config) |\n| `VOYAGIER_API_URL` | API base URL (default: `https://travel.voyagier.com/api`; the CLI appends `/graphql`) |\n\n## How It Works\n\nThin client over Voyagier's GraphQL API — the same API the web app uses. Everything syncs both ways. A plan is a goal graph; searching composes selections against goals, and air, accommodation, activity, and places suppliers are all surfaced through one unified selection model.\n\n## Getting Access\n\nVoyagier access is granted, not open signup — **request access at [voyagier.com/agents](https://voyagier.com/agents)**. That's the gate for advisors, trip-planner customers, and agent builders alike.\n\nOnce your account is granted API access, mint a personal access token at [travel.voyagier.com/me/settings/tokens](https://travel.voyagier.com/me/settings/tokens) and you're in. Two account tiers use the CLI today:\n\n- **Travel advisors** — manage a book of clients (`voyagier clients`); plans are created against a client (`--client`).\n- **Trip planners** — paying customers planning their own travel. Just run `voyagier plan-trip` — no client setup, no `--client` flag. (`voyagier whoami` shows your tier.)\n\nNon-admin tokens expire (90 days max, 30 by default) — mint a fresh one when yours lapses.\n\n> **Tip:** prefer `voyagier login` (interactive prompt) over `voyagier auth set-token <token>` — it keeps your token out of shell history. For scripts, use the `VOYAGIER_TOKEN` env var.\n\n## Claude Desktop Extension (MCPB)\n\nThe MCP server is also packaged as a Claude Desktop extension bundle (MCPB). Build it from the repo with `scripts/build-mcpb.sh`, which produces `dist-mcpb/voyagier-<version>.mcpb`. To install, drag the `.mcpb` file into Claude Desktop → Settings → Extensions, then enter your Personal Access Token when prompted.\n\n## Privacy Policy\n\nData processed through the CLI and Voyagier services is handled per the [Voyagier privacy policy](https://www.voyagier.com/privacy-policy).\n\n## License\n\n[Apache-2.0](LICENSE) — Copyright 2026 Voyagier, Inc. Use of Voyagier services through the CLI is subject to the [Voyagier Terms of Service](https://voyagier.com/terms). \"Voyagier\" and the Voyagier logo are trademarks of Voyagier, Inc.; the Apache-2.0 license does not grant trademark rights.\n",
  "bytes": 16227,
  "sha": "b046ab42af36aacec05c3390c202aa811339d549b4ac72fdbf6eb0f425b5acdb",
  "repo_slug": "voyagier-travel/voyagier-cli",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_com_voyagier_cli_af88a2d5/readme"
}