Uber MCP

Unofficial MCP server for Uber — request rides, watch trips, browse activity through any AI assistant via stdio or HTTP+OAuth.

Uber MCP Server

License: MIT Node.js TypeScript MCP

Unofficial Model Context Protocol server for Uber — request rides, watch a trip in progress, browse activity history and pay through any AI assistant that speaks MCP.

Not affiliated with Uber. Wraps the rider web API for personal use.

What This MCP Server Does

This MCP server gives AI assistants (Claude Code, Claude Desktop, Cursor, Codex, etc.) access to your Uber account. It exposes 35 tools that let an AI:

  • 🚗 List available products (UberX, Comfort, Black, Reserve, …) with real‑time prices and ETAs
  • 🔍 Autocomplete pickup / dropoff addresses, resolve coordinates, refine venue access points
  • 📦 Request and cancel rides, watch the trip status until the driver arrives
  • 💬 Read and route through driver chat threads
  • 💳 List payment options, build the checkout action result and dispatch the trip
  • 📜 Browse past + upcoming activities, full trip details, fiscal receipts and arrears
  • 🎁 Get ranked promotional offers, Uber One membership state and home‑screen banners
  • 🧭 One‑shot composite tool to go from "two addresses" to a confirmed trip

Two Authentication Modes

ModeTransportLoginBest for
HTTP + OAuth 2.1Streamable HTTPReal Uber login (Google / e‑mail / OTP) on a server‑side Chromium streamed to your browser as a <canvas>Multi‑user deploys, remote MCP, sharing with friends
stdioStandard input / outputCookies exported from a one‑off HTTP login into a .env fileLocal single‑user setup, fastest to wire up

You can run either mode independently; the same tool definitions back both.

Why a remote browser instead of a paste‑your‑token flow?

The Uber rider web is gated by PerimeterX (~40 KB device fingerprint generated by JS in the browser) and Arkose Labs (FunCaptcha). Reproducing those server‑side is out of scope, and X-Frame-Options: SAMEORIGIN on auth.uber.com blocks the obvious iframe approach. Same‑origin policy + HttpOnly cookies also rule out client‑side capture.

Solution: when you hit /login/start, the MCP server launches a real Chromium via Playwright, navigates to auth.uber.com, and streams JPEG frames over WebSocket to a <canvas> in your browser. Your input goes back over the same socket and is dispatched via Chromium's CDP. PerimeterX and Arkose see a real browser; you see and operate Uber's official login page; the MCP server captures the resulting cookies (including HttpOnly ones) the moment the post‑login redirect lands on m.uber.com/go/home.

Zero copy‑paste. Zero browser extension. Real Uber login.

Prerequisites

  • Node.js ≥ 20
  • An active Uber account
  • For HTTP+OAuth mode: nothing else — npm install downloads Chromium via Playwright's postinstall step
  • For stdio mode: cookies from a successful HTTP login (see below)

Check your install with node -v and npm -v.

Installation

1. Clone and build

git clone https://github.com/AriOliv/uber-mcp.git
cd uber-mcp
npm install      # also installs Chromium for Playwright (~170 MB)
npm run build

2. Pick a mode

Option A — HTTP + OAuth 2.1 (recommended)

# Generate a JWT signing secret (≥32 chars)
echo "MCP_JWT_SECRET=$(openssl rand -hex 32)" >> .env
echo "PORT=3001" >> .env

# Run with auto-reload
npm run dev

Then register the server with your client.

Claude Code
claude mcp add --transport http uber http://localhost:3001/mcp

Run /mcp inside Claude Code → click uber → it'll open a browser window with a <canvas> showing Uber's official login screen, streamed live from the server. Sign in normally (Google or e‑mail+OTP). When you land on m.uber.com/go/home the MCP captures cookies, mints an OAuth code and redirects back to your client.

Cursor

Add to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "uber": {
      "type": "http",
      "url": "http://localhost:3001/mcp"
    }
  }
}

Cursor will trigger the OAuth flow on first use.

Codex
codex mcp add --transport http uber http://localhost:3001/mcp

Option B — stdio (single user)

stdio mode reuses cookies captured by a one‑off HTTP login.

  1. Start npm run dev once and complete the canvas login.
  2. With NODE_ENV unset (the default), hit GET /debug/users to confirm your userSub.
  3. Read the cookie header from the server logs (or open DevTools on m.uber.com and copy Cookie: from any request).
  4. Drop them into .env:
cp .env.example .env
# fill in UBER_COOKIE_HEADER, UBER_USER_SUB, UBER_CITY_ID, UBER_SESSION_TYPE
Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "uber": {
      "command": "node",
      "args": ["/absolute/path/to/uber-mcp/build/index.js"],
      "env": {
        "UBER_COOKIE_HEADER": "jwt-session=...; udi-id=...; ...",
        "UBER_USER_SUB": "ed1b0c3a-...",
        "UBER_CITY_ID": "458",
        "UBER_SESSION_TYPE": "desktop_session"
      }
    }
  }
}
Claude Code (stdio)
claude mcp add --transport stdio uber \
  --env "UBER_COOKIE_HEADER=jwt-session=...; udi-id=...; ..." \
  --env UBER_USER_SUB=ed1b0c3a-... \
  --env UBER_CITY_ID=458 \
  --env UBER_SESSION_TYPE=desktop_session \
  -- node /absolute/path/to/uber-mcp/build/index.js

[!NOTE] Uber sessions last ~24 h. There's no refresh endpoint — when the cookie expires, just hit /login/start again to capture a new set.

Available Tools

📍 Pickup / Dropoff

ToolDescription
uber_pudo_searchAutocomplete address search — pickup or dropoff
uber_pudo_resolveResolve a place ID to coordinates and full address
uber_pudo_refineRefine within a venue (airport terminals, multi‑access spots)
uber_navigation_routePolyline / turn‑by‑turn route between origin and destinations

🚗 Products & Booking

ToolDescription
uber_status_getCity, current trip, nearby vehicles — also an auth probe
uber_products_listUberX / Comfort / Black with real‑time fares + ETAs
uber_pre_plus_ones_getVenue + first‑time UX info for a pickup
uber_reservation_data_getBooking time ranges + Uber Reserve availability
uber_offers_rankedRanked promotional offers in a city
uber_pre_checkout_actions_getPre‑checkout actions (auto‑built into the next step)
uber_trip_requestSmart wrapper — auto‑builds checkoutActionResult if missing
uber_cancellation_info_getCancellation fees / messaging
uber_trip_cancelCancel an active trip
uber_ride_book_quickOne‑shot: search → resolve → products → trip_request
uber_trip_status_watchPoll uber_status_get until clientStatus changes

📜 Activity History

ToolDescription
uber_activities_listPast + upcoming activities (riders.uber.com)
uber_activities_upcomingUpcoming via REST (www.uber.com)
uber_activities_pastPast via REST (www.uber.com)
uber_trip_getFull details of a single trip
uber_receipt_getDetailed receipt — fare breakdown, distance, duration
uber_receipt_send_emailEmail a receipt
uber_invoice_status_getFiscal invoice / NF‑e status (Brazil)
uber_arrears_getOutstanding payment balance

💬 Driver Chat

ToolDescription
uber_thread_by_tracking_getFind chat thread UUID by trip UUID
uber_thread_getRead messages in a chat thread

👤 Profile

ToolDescription
uber_user_riders_getFull profile: name, payment profiles, Uber Cash, memberships
uber_user_currentQuick profile via REST
uber_user_travel_statusWhether the user is currently on a trip
uber_membership_attributesUber One state + benefits eligibility
uber_navlinks_getWeb navigation links
uber_tax_forms_checkWhether tax forms (1099‑equivalent) are available

💳 Payments & Promos

ToolDescription
uber_payment_options_listSaved payment methods from the payments hub
uber_promo_pill_getPromo banner from the home screen
uber_product_suggestions_listSuggested product types based on history
uber_map_hero_productsHero products on the map home screen

Example Prompts

Once connected, ask your AI assistant:

"qual o status da minha corrida atual?"

"quanto custa um UberX da Av. Paulista até o aeroporto de Congonhas agora?"

"peça um Comfort da minha posição até a Rua Tabapuã, 82, Itaim"

"liste meus 5 últimos trajetos com motorista e valor"

"existe algum cupom ativo na minha conta hoje?"

"o motorista chegou? me avise quando o status mudar de ACCEPTED para ON_TRIP"

[!TIP] The uber_ride_book_quick composite handles the full booking dance internally — pickup search, resolve, dropoff search, resolve, products, pre‑checkout, trip request. Useful when you just want to say "book me a ride from X to Y".

[!CAUTION] uber_trip_request and uber_ride_book_quick charge the user's payment method and dispatch a real driver. Always confirm with the user before calling.

Architecture

┌──────────────────┐    OAuth 2.1     ┌──────────────────────┐    Cookies + JWT     ┌─────────────────┐
│  AI assistant    │◄────────────────►│   uber-mcp server    │◄────────────────────►│  Uber API       │
│  (Claude/Cursor) │   /mcp endpoint  │   (Express + MCP)    │   m.uber.com         │  (rider web)    │
└──────────────────┘                  └──────────────────────┘   riders.uber.com    └─────────────────┘
                                              │  ▲                www.uber.com
                                              │  │                payments.uber.com
                                              ▼  │
                                  ┌──────────────────────────┐
                                  │  /login/start            │  HTML — canvas + WS
                                  │  (browser of the user)   │  ◄──────────►
                                  └──────────────────────────┘     JPEG frames
                                              ▲                    + input events
                                              │ CDP screencast
                                              ▼
                                  ┌──────────────────────────┐
                                  │  Playwright Chromium     │  drives auth.uber.com
                                  │  (server‑side, headless) │  PX + Arkose see real Chrome
                                  └──────────────────────────┘
  • Stateless transport: each /mcp call creates a fresh StreamableHTTPServerTransport + McpServer bound to the authenticated user's session — handles concurrent users without sticky sessions.
  • Server‑side remote browser: one Playwright Chromium per login session. CDP Page.startScreencast streams JPEG frames over WebSocket; CDP Input.dispatch{Mouse,Key}Event forwards user input. Capacity bounded by MAX_BROWSER_SESSIONS.
  • Subdomain warm‑up: after the post‑login redirect on m.uber.com, the server silently visits riders.uber.com, www.uber.com and payments.uber.com to materialize their domain‑specific session cookies before capturing the bundle.
  • Cookie‑based auth, no refresh: Uber doesn't expose a refresh endpoint. When jwt-session expires (≈24 h), the user re‑hits /login/start.
  • OAuth 2.1 + PKCE S256, audience‑bound HS256 JWTs, opaque rotating refresh tokens (for the MCP layer, separate from Uber's session).
  • Smart uber_trip_request: auto‑builds payment.checkoutActionResult from getPreCheckoutActions if missing — agents only need to pass the meta from uber_products_list plus paymentProfileUUID.

Development

npm run dev          # http-server with auto-reload (tsx watch)
npm run dev:stdio    # stdio with auto-reload
npm run build        # tsc → build/
npm run typecheck    # tsc --noEmit

Project layout:

src/
  index.ts                       tool definitions + executeTool dispatcher + stdio entry
  http-server.ts                 Express + OAuth + Streamable HTTP + WS upgrade
  http/
    store.ts                     in-memory OAuth + UberCredentials + browser session stores
    provider.ts                  OAuthServerProvider implementation
    session-provider.ts          SessionTokenProvider + expiry pruning loop
    login-router.ts              entry shell ("Continue" button)
    remote-browser.ts            RemoteBrowserSession (Playwright + CDP + warm‑up)
    remote-browser-router.ts     /login/start + WS /login/ws/:sessionId

Security & Disclaimer

  • 🔒 In HTTP mode, Uber cookies live only in memory — never written to disk. Process restart = re‑login.
  • 🚫 Don't commit .env, HAR files or any DevTools captures — they contain session cookies. The .gitignore blocks all common spots.
  • ⚠️ Unofficial. Uber does not publish a public consumer‑facing API. This wraps the rider website's endpoints, which can change without notice. Use at your own discretion and respect Uber's Terms of Service.
  • 🛡️ The remote‑browser flow may surface PerimeterX or Arkose challenges during login. They're solvable through the canvas (clicking images, dragging puzzles, etc.) — your IP reputation matters: residential IPs get fewer challenges than datacenter IPs.
  • 💸 uber_trip_request and uber_ride_book_quick move real money. Always confirm with the user before calling.

Contributing

Issues and PRs welcome. When opening an issue please include:

  • Output of npm run typecheck
  • Whether you're using stdio or HTTP+OAuth mode
  • Redacted request/response (no cookies) when reporting an API failure

License

Released under the MIT License.


Made by Ari and Claude a.k.a Claudão.

관련 서버