Skip to main content
Glama
README.md
# Marriott MCP

**Your Marriott Bonvoy account, as tools an AI agent can actually use.**

Marriott MCP is a [Model Context Protocol](https://modelcontextprotocol.io/) server that signs into *your* marriott.com session and exposes it to clients such as Claude, ChatGPT, Cursor, or Grok.

It is **not** Marriott’s partner/CRS API. There is no public consumer API for points, elite nights, or trips. This server drives a real Chrome profile the same way you would, then wraps that session as MCP tools, resources, and skills.

Clone it, add Bonvoy credentials (`.env` **or** the login page the MCP opens — never in Grok chat), run it on your machine.

> Unofficial project. Not affiliated with, endorsed by, or maintained by Marriott International.

---

## What you get

| Surface | What it does |
| --- | --- |
| **Read** | Account, trips, stay history, **property search + availability** (URLs and dates from MCP, not the web) |
| **Write** | Create, modify, and cancel reservations |
| **Human gate** | Every write sends `elicitation/create` and **waits**. Nothing is booked or cancelled until you press Confirm |
| **Skills** | Agent Skills over MCP ([SEP-2640](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2640)): `skills/list`, `skills/get`, files on `skill://` |
| **Transport** | stdio for local agents, Streamable HTTP + OAuth 2.1 PKCE for remote connectors |

Write tools never collect card numbers, CVV, or passwords through elicitation. If Marriott’s checkout asks for a card, the flow aborts.

---

## How it works

```
AI client  ── MCP (stdio or HTTPS) ──►  Marriott MCP
                                            │
                                            ▼
                                   persistent Chrome
                                   (your Bonvoy session)
                                            │
                                            ▼
                                      marriott.com
```

Akamai blocks bare HTTP from datacenter IPs. A headed Chrome profile with a normal login is the reliable path.

**Writes** do not run when the model “says confirm.” The server pauses the tool, emits a nested `elicitation/create` (Confirm / Cancel). Decline, cancel, or timeout → `changed: false`, Playwright never starts the mutation.

---

## Tools

**Read**

- `marriott_status` — signed in, page, first name
- `marriott_open` / `marriott_login` — session
- `marriott_me` — points, elite, nights
- `marriott_trips` — upcoming reservations
- `marriott_activity` — GraphQL activity (`types=all|stay|bonus`; `entries` + `type_counts`)
- `marriott_stays` — stay history (`months` default **240**)
- `marriott_search` — hotels for destination + dates (`property_id`, official URL)
- `marriott_availability` — rates + property URL for one hotel
- `marriott_page` — rooms, prices, confirmation number, structured errors
- `marriott_click` / `marriott_fill` / `marriott_dismiss` — interact (no cards/captcha)
- `marriott_goto` — marriott.com URLs only

**Write** (elicitation required)

- `marriott_reservation_create`
- `marriott_reservation_modify`
- `marriott_reservation_cancel`
- `marriott_book` — first lists rooms A/B/C in chat; books only after the human picks and says confermo

**Skills fallback** (if the client has no `skills/list` yet)

- `marriott_skills_list`
- `marriott_skills_get`

**Bugs** (saved on the MCP host, secrets stripped)

- `marriott_report_bug` — title, what happened, tool, arguments, log
- `marriott_bugs_list` / `marriott_bugs_get`

Manuals ship next to the tools:

- `skill://marriott-stays/SKILL.md`
- `skill://marriott-reservations/SKILL.md`

---

## Run your own copy

Requires Python 3.11+, Google Chrome, and a display (headed Chrome).

```bash
git clone https://github.com/emrgim/marriott-mcp.git
cd marriott-mcp
python3 -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -r requirements.txt
playwright install chrome
```

Bonvoy sign-in (pick one):

- `.env` with `MARRIOTT_EMAIL` / `MARRIOTT_PASSWORD`, or
- skip `.env`: the first Marriott tool sends an **elicitation URL**. Open `/login/{token}`, enter Bonvoy there. Never type the password in Grok.

### Local stdio (Claude Desktop, Cursor, Hermes, …)

```json
{
  "mcpServers": {
    "marriott": {
      "command": "/absolute/path/to/marriott-mcp/.venv/bin/python",
      "args": ["/absolute/path/to/marriott-mcp/src/mcp_server.py"],
      "env": {
        "DISPLAY": ":0"
      }
    }
  }
}
```

On macOS, omit `DISPLAY` if Chrome can open windows normally.

### Streamable HTTP + OAuth (Grok custom connector, remote agents)

```bash
export MARRIOTT_PUBLIC_BASE=https://your-https-host.example
export MARRIOTT_GROK_MCP_HOST=127.0.0.1
export MARRIOTT_GROK_MCP_PORT=8099
export DISPLAY=:0
.venv/bin/python src/grok_http.py
```

Put HTTPS in front (reverse proxy or tunnel). Well-known OAuth and `/oauth/*` stay unauthenticated; MCP POST `/` and `/mcp` require a bearer token from PKCE.

Connector form (typical):

- Server URL: `https://your-https-host.example`
- Client ID: `grok`
- Client secret: empty
- Token auth: none (PKCE)
- Scope: `mcp:tools`

**Grok Bot:** if the connect card opens `/oauth/authorize` with no query, that is a client bug (missing `redirect_uri`). Set `GROK_MCP_TOKEN` and `MARRIOTT_OAUTH_DISCOVERY=0` on the host, then connect with `Authorization: Bearer <token>` (no OAuth discovery). Bonvoy credentials stay in `.env` or `/login/{token}`, never in chat.

A systemd user unit template lives in `deploy/marriott-grok-mcp.service` — copy it and adjust paths.

---

## Environment

See `.env.example`. Never commit `.env`. Chrome profile and cookies stay in `.session/` (gitignored).

| Variable | Purpose |
| --- | --- |
| `MARRIOTT_EMAIL` | Bonvoy email or member number |
| `MARRIOTT_PASSWORD` | Bonvoy password |
| `MARRIOTT_PUBLIC_BASE` | Public HTTPS origin for OAuth + confirm links |
| `MARRIOTT_GROK_MCP_HOST` / `_PORT` | HTTP bind |
| `MARRIOTT_ELICIT_TIMEOUT` | Seconds to wait for Confirm (default 180) |

---

## Protocol notes

- MCP protocol versions: `2025-11-25`, `2025-06-18`, `2025-03-26`, `2024-11-05`
- Skills extension: `io.modelcontextprotocol/skills` with `directoryRead: true` (draft SEP-2640)
- Write path: nested `elicitation/create` on the Streamable HTTP SSE stream; optional `/confirm/{id}` page
- Confirming a write in chat is not enough. The button is.

More detail: [`docs/MCP.md`](docs/MCP.md).

---

## Safety

- Credentials live only in your `.env` and OS keychain-equivalent. This repo ships empty placeholders.
- Destructive tools are annotated `destructiveHint: true`.
- The server refuses unknown cancel/delete tool names.
- Do not point a public connector at an account you do not control.

---

## License

MIT. See [LICENSE](LICENSE).

Maintenance

ActivityMaintained
ResponsivenessResponsive