
Uber MCP Server 
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
| Mode | Transport | Login | Best for |
|---|---|---|---|
| HTTP + OAuth 2.1 | Streamable HTTP | Real 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 |
| stdio | Standard input / output | Cookies exported from a oneβoff HTTP login into a .env file | Local 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.
Available Tools
π Pickup / Dropoff
| Tool | Description |
|---|---|
uber_pudo_search | Autocomplete address search β pickup or dropoff |
uber_pudo_resolve | Resolve a place ID to coordinates and full address |
uber_pudo_refine | Refine within a venue (airport terminals, multiβaccess spots) |
uber_navigation_route | Polyline / turnβbyβturn route between origin and destinations |
π Products & Booking
| Tool | Description |
|---|---|
uber_status_get | City, current trip, nearby vehicles β also an auth probe |
uber_products_list | UberX / Comfort / Black with realβtime fares + ETAs |
uber_pre_plus_ones_get | Venue + firstβtime UX info for a pickup |
uber_reservation_data_get | Booking time ranges + Uber Reserve availability |
uber_offers_ranked | Ranked promotional offers in a city |
uber_pre_checkout_actions_get | Preβcheckout actions (autoβbuilt into the next step) |
uber_trip_request | Smart wrapper β autoβbuilds checkoutActionResult if missing |
uber_cancellation_info_get | Cancellation fees / messaging |
uber_trip_cancel | Cancel an active trip |
uber_ride_book_quick | Oneβshot: search β resolve β products β trip_request |
uber_trip_status_watch | Poll uber_status_get until clientStatus changes |
π Activity History
| Tool | Description |
|---|---|
uber_activities_list | Past + upcoming activities (riders.uber.com) |
uber_activities_upcoming | Upcoming via REST (www.uber.com) |
uber_activities_past | Past via REST (www.uber.com) |
uber_trip_get | Full details of a single trip |
uber_receipt_get | Detailed receipt β fare breakdown, distance, duration |
uber_receipt_send_email | Email a receipt |
uber_invoice_status_get | Fiscal invoice / NFβe status (Brazil) |
uber_arrears_get | Outstanding payment balance |
π¬ Driver Chat
| Tool | Description |
|---|---|
uber_thread_by_tracking_get | Find chat thread UUID by trip UUID |
uber_thread_get | Read messages in a chat thread |
π€ Profile
| Tool | Description |
|---|---|
uber_user_riders_get | Full profile: name, payment profiles, Uber Cash, memberships |
uber_user_current | Quick profile via REST |
uber_user_travel_status | Whether the user is currently on a trip |
uber_membership_attributes | Uber One state + benefits eligibility |
uber_navlinks_get | Web navigation links |
uber_tax_forms_check | Whether tax forms (1099βequivalent) are available |
π³ Payments & Promos
| Tool | Description |
|---|---|
uber_payment_options_list | Saved payment methods from the payments hub |
uber_promo_pill_get | Promo banner from the home screen |
uber_product_suggestions_list | Suggested product types based on history |
uber_map_hero_products | Hero 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_quickcomposite 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_requestanduber_ride_book_quickcharge 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
/mcpcall creates a freshStreamableHTTPServerTransport+McpServerbound to the authenticated user's session β handles concurrent users without sticky sessions. - Serverβside remote browser: one Playwright Chromium per login session. CDP
Page.startScreencaststreams JPEG frames over WebSocket; CDPInput.dispatch{Mouse,Key}Eventforwards user input. Capacity bounded byMAX_BROWSER_SESSIONS. - Subdomain warmβup: after the postβlogin redirect on
m.uber.com, the server silently visitsriders.uber.com,www.uber.comandpayments.uber.comto materialize their domainβspecific session cookies before capturing the bundle. - Cookieβbased auth, no refresh: Uber doesn't expose a refresh endpoint. When
jwt-sessionexpires (β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βbuildspayment.checkoutActionResultfromgetPreCheckoutActionsif missing β agents only need to pass themetafromuber_products_listpluspaymentProfileUUID.
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 --noEmitProject 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/:sessionIdSecurity & 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.gitignoreblocks 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_requestanduber_ride_book_quickmove real money. Always confirm with the user before calling.
git clone https://github.com/AriOliv/uber-mcp.git
cd uber-mcp
npm install # also installs Chromium for Playwright (~170 MB)
npm run buildBefore it works, you'll need: UBER_COOKIE_HEADERUBER_USER_SUBUBER_CITY_IDUBER_SESSION_TYPE
Prerequisites
- Node.js β₯ 20
- An active Uber account
- For HTTP+OAuth mode: nothing else β
npm installdownloads Chromium via Playwright'spostinstallstep - 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 build2. 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 devThen register the server with your client.
Claude Code
claude mcp add --transport http uber http://localhost:3001/mcpRun /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/mcpOption B β stdio (single user)
stdio mode reuses cookies captured by a oneβoff HTTP login.
- Start
npm run devonce and complete the canvas login. - With
NODE_ENVunset (the default), hitGET /debug/usersto confirm youruserSub. - Read the cookie header from the server logs (or open DevTools on
m.uber.comand copyCookie:from any request). - Drop them into
.env:
cp .env.example .env
# fill in UBER_COOKIE_HEADER, UBER_USER_SUB, UBER_CITY_ID, UBER_SESSION_TYPEClaude 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/startagain to capture a new set.
No common issues documented yet. If you hit a problem, the repository's GitHub Issues page is the best place to look.
Licensed under MITβ you can use, modify, and redistribute it under that license's terms.
View the full license file on GitHub β