Skip to main content
Glama
README.md
# xcape

[![CI](https://github.com/ari-systemics/xcape/actions/workflows/ci.yml/badge.svg)](https://github.com/ari-systemics/xcape/actions/workflows/ci.yml)

Vacation-quoting MCP server for travel agents, plus a cross-platform assistant skill that turns a plain-language client brief ("family of four, Lisbon, spring break, $8k") into a priced, bookable proposal with stays, activities, and dining.

## How it works

One stdio MCP server composes three paid APIs:

| Leg           | Source                                    | What you get                                                        | Cost shape                                  |
| ------------- | ----------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------- |
| Stays         | Bright Data Web Scraper API (Booking.com) | Live-scraped hotel listings with nightly rates                      | Per record (~$1–1.5/1K); 30–120s per search |
| Activities    | Viator Partner API v2                     | 300k+ bookable tours/activities, real availability, affiliate links | Free (commission model)                     |
| Dining & POIs | Google Places API (New)                   | Restaurants, ratings, price level, hours, Maps links                | Per request, tiered by field mask           |

Every proposal carries an **indicative-rates disclaimer**: prices are captured live at quote time and must be re-confirmed at booking. There are no booking transactions — proposals link out (Viator links carry your affiliate campaign for commission attribution).

## Tools

- `build_proposal` — one-shot: full request in, ranked itinerary + cost breakdown + Markdown proposal out
- `build_options_page` — interactive HTML options page (lodging, transfers, experiences, day trips, dining); the agent picks options with the client and clicks "Generate quote" in-page for the final branded, printable quote
- `search_stays` — live Booking.com scrape (slow, per-record billed; keep `maxResults` ≤10)
- `search_activities` — Viator product search with persona-aware tags
- `get_activity_availability` — firm per-person pricing for specific dates
- `search_dining` — Google Places search, profile-aware
- `enrich_place` — Place Details for shortlist finalists only

Profiles (`family`, `bachelorette`, `couples`, `solo`, `seniors`, `adventure`, `luxury`) drive activity tags, dining types, and scoring. A "family of four" yields kid-friendly activities and suites; a bachelorette yields adult group experiences and nightlife-adjacent dining.

## Setup

Requires Node ≥ 20. The installer detects the platform, checks Node, installs dependencies, builds, walks you through credentials, validates the config, and optionally registers the server with Claude Desktop:

```bash
# macOS / Linux (Git Bash on Windows also works)
./install.sh
```

```powershell
# Windows (PowerShell)
powershell -ExecutionPolicy Bypass -File install.ps1
```

Manual equivalent:

```bash
npm install
npm run build
cp .env.example .env   # then fill in keys
npm run check-config
```

Note: the project `.env` is authoritative — it overrides inherited shell variables, so a stale exported key in your shell profile cannot silently win over the configured `.env`.

### Getting credentials

**Bright Data** (stays) — _optional; `search_stays` returns a setup error until configured, the other legs work without it_

1. Sign up at brightdata.com → account settings → copy your API key → `BRIGHTDATA_API_KEY`
2. Dashboard → Web Scraper API → dataset library → find the **Booking.com listings search** scraper → copy its dataset ID → `BRIGHTDATA_BOOKING_DATASET_ID`
3. Note: the exact input schema (URL vs structured search fields) depends on the dataset variant; if `search_stays` errors on input validation, check the dataset's input spec in the dashboard and adjust `src/providers/brightdata.ts`.

**Google Places (New)** (lodging + dining)

1. Google Cloud Console → create project → enable billing
2. Enable **"Places API (New)"** (not the legacy Places API)
3. Create an API key → `GOOGLE_MAPS_API_KEY`. If you restrict the key, make sure `places.googleapis.com` is in the allowed list — a key restricted to other Google services fails with `API_KEY_SERVICE_BLOCKED`.

**Viator Partner API v2** (activities)

1. Sign up at partners.viator.com (free) → request a Basic Access API key
2. Sandbox key is issued immediately → `VIATOR_API_KEY` with `VIATOR_ENV=sandbox`
3. Production key is generated separately in the portal and can take ~24h to activate. Sandbox and production keys are **not** interchangeable.
4. Copy your affiliate campaign value → `VIATOR_CAMPAIGN_VALUE` (appended to every activity link for commission tracking)

### Configuration

```bash
BRIGHTDATA_API_KEY=
BRIGHTDATA_BOOKING_DATASET_ID=
GOOGLE_MAPS_API_KEY=
VIATOR_API_KEY=
VIATOR_ENV=sandbox            # switch to production once your prod key activates
VIATOR_CAMPAIGN_VALUE=
AGENCY_CURRENCY=USD
```

Keys are shared agency-wide: every agent's client quotes against the same accounts and affiliate ID.

### Agency branding (letterhead / logo)

Proposals render with your letterhead when branding is configured — logo, agency name, tagline, contact line at the top and a "Prepared by …" sign-off at the foot:

```bash
AGENCY_NAME=Sunrise Travel Co
AGENCY_LOGO_URL=https://your-domain.com/logo.png   # hosted URL renders in Markdown viewers
AGENCY_CONTACT=+1 555 0100 · hello@sunrise.travel
AGENCY_TAGLINE=Tailor-made trips
```

Per-proposal overrides are supported via `build_proposal`'s optional `branding` argument (`agencyName`, `logoUrl`, `contactLine`, `tagline`) — useful for multi-brand agencies or co-branded documents. The resolved branding is also exposed as `proposal.agency` in the structured JSON for downstream renderers (PDF, email).

## Install in your assistant

The fastest paths, in order:

1. **Claude Desktop, guided**: run `./install.sh` / `install.ps1` and answer "y" at the registration prompt. It merges an `xcape` entry into `claude_desktop_config.json` (backing up the existing file first) with credentials taken from `.env`. Restart Claude Desktop afterwards.
2. **One-click bundle (DXT)**: `npm run pack:dxt` builds a `.dxt` desktop-extension file (see `manifest.json`); double-clicking it in Claude Desktop installs the server and prompts for the API keys through the UI.
3. **Any other client**: `npm run print-config` prints a ready-to-paste `mcpServers` snippet with absolute paths and the current credentials, plus the config-file location for this machine.

**Claude Code**:

```bash
claude mcp add xcape -- node /absolute/path/to/xcape/dist/index.js
```

**Kimi Code / Cursor / others** — same `command`/`args`/`env` shape as the `--print-config` snippet in their MCP settings.

**ChatGPT** — MCP support varies by client; where custom MCP servers are configurable, use the same command/args/env. Otherwise paste `skills/xcape-trip-planner/SKILL.md` into the conversation as instructions and drive the server through any MCP bridge.

## The skill

`skills/xcape-trip-planner/` is a platform-neutral assistant skill (Claude Agent Skills format — YAML frontmatter + Markdown, equally usable as Kimi skill or ChatGPT custom instructions). It teaches the assistant to:

1. Run intake on the agent's brief (party, dates, destination, budget, vibe) and pick a profile
2. Drive the tools in a cost-aware order
3. Write the proposal from a fixed template: totals + per-person pricing, day-by-day itinerary, alternatives, verbatim booking links, indicative-rates disclosure, and an explicit Gaps section when a data leg fails

Install it alongside the MCP server so the model knows how to use the tools well.

## Development

```bash
npm test          # vitest + msw; no real keys needed, no network
npm run build     # tsc
npx @modelcontextprotocol/inspector node dist/index.js   # manual tool testing
```

## Cost guardrails (built in)

- Bright Data: results hard-capped at 20/call; `build_proposal` defaults to ≤10
- Google: field masks pinned to narrow constants — tools never accept arbitrary field lists (a snapshot test guards this)
- Viator: search counts clamped to provider max (50); `Retry-After` honored on 429
- Google ToS: no long-term warehousing of place data — caching is in-memory, per-process only

## Known limitations / roadmap

- **Stays latency**: live scraping takes 30–120s and bills per record. If this proves too slow in practice, the fix is adding a hotel affiliate/rates API as a fast path — not built yet.
- **No flights**: a Bright Data Google Flights scraper can be added as `search_flights` later.
- **No booking**: quoting + links only. In-chat Viator booking requires Viator Full+Booking approval, certification, and PCI-aware payments.
- **Local stdio only**: each agent installs the server on their own machine with the shared keys. A hosted multi-tenant version is a separate project.

TDQS

A4.3/5.0

Scored across 7 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: search tools cover different resource types (stays, activities, dining), availability is specific to activities, enrich_place provides details for any place, and the two build tools produce different outputs (a text proposal vs. an interactive HTML page). No two tools overlap in function.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern (build_proposal, search_stays, get_activity_availability, enrich_place). The verbs are specific and the nouns clearly indicate the target resource or artifact, making the naming predictable and intuitive.

Tool Count5/5

Seven tools is well-scoped for a travel planning and quoting server. Each tool covers a necessary step in the workflow (searching, availability, enrichment, and output generation) without redundancy or bloat.

Completeness4/5

The surface covers the core trip-planning lifecycle: search stays, activities, dining; check activity availability; enrich places; and generate both a proposal and an options page. Minor gaps exist, such as no dedicated transfer search (transfers are mentioned in build_options_page but not searchable) and no explicit quote generation tool, though these are partially handled within the build tools.

Maintenance

ActivitySlowing
ResponsivenessNo issues