uber-mcp
An MCP server that lets an AI assistant use your own Uber account to find places, compare live prices, book and follow real rides, and review your trip history.
Find places — list your saved places, or search Uber's places by name, saved label, or
lat,lng(each with a place id; airports include terminals).Compare live prices — every ride option for a trip with upfront price or taxi range, seats, pickup ETA, arrival time, and the matched pickup/drop-off.
Request a ride — two-step: a preview with a single-use
confirm_token, then booking after your yes, blocked if the price rose or a cap would be exceeded.Reserve a future ride — native Uber Reserve: preview, confirm, read reservation status, and cancel with a fee preview.
Follow the live ride — driver name/rating, car, plate, PIN, fare, stops, plus separate pickup and destination arrival estimates.
Cancel the current ride — with Uber's cancellation notice and any fee previewed first.
Review history — upcoming and past trips, paged, with optional details (category, receipt vehicle, route, times, distance); or one trip by id.
Read your account — first name, rating, completed trips, Uber One, payment methods, Uber Cash, money owed, and the server's booking caps and 24-hour spend.
Check status and sign in — sign-in state, request budget, pauses, last error, cached canary, plus
uber_connectfor a hosted sign-in link.Safety built in — booking off until you set per-ride and 24-hour caps, one ride at a time, audit log, admin freeze, and no automatic retries on unknown outcomes.
Provides tools for interacting with Uber rider services: finding places, comparing live ride options and prices, requesting and booking rides with safety caps, tracking live ride status and driver details, cancelling rides, and reading trip history and account information.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@uber-mcp How much is an Uber from my Home to SFO right now?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
uber-mcp
An MCP server for Uber rides. It lets an AI assistant (Claude, ChatGPT, Cursor, ...) find places, compare every ride option with Uber's live prices, request a ride once you have said yes to the exact price, follow the live ride (driver, car, plate, PIN, arrival time), cancel it, and read your trip history.
Unofficial. Not affiliated with or endorsed by Uber Technologies, Inc. Uber has no public API for booking rides as a rider; this server uses the same endpoints Uber's own rider website uses (
m.uber.comandriders.uber.com), signed in as you, with the session of a browser you signed in to yourself. Uber can change those endpoints at any time, and the server then stops working until it is updated. Use it with your own account, for your own rides; Uber's terms of use apply to you, and whether automated use of your account is acceptable to Uber is your risk.
Requesting a ride spends your money and sends a real car. The server never does that on one call: every request is a preview first and a single-use confirm token second, within price caps you set, and booking stays off until you set them (Booking safety).
Requirements
An Uber rider account with a payment method, in a city where Uber's rider website (
m.uber.com) offers rides.uv (it fetches Python 3.12 if needed), or Docker for a server.
Google Chrome for signing in (or Chromium, see Signing in).
Quick start
Sign in once. A browser window opens on Uber's own sign-in page; sign in as usual (a code, Google, Apple or a QR code). It closes once you are signed in, and the session is saved for the server.
uvx --from "uber-mcp[login]" uber-mcp loginAdd the server to your client. It runs over stdio, started by the client. As configured here it can look up places, prices, rides and trips but cannot book: booking stays off until step 3.
Claude Code:
claude mcp add uber -- uvx uber-mcpClaude Desktop, Cursor and most other clients: add to the client's MCP configuration
{ "mcpServers": { "uber": { "command": "uvx", "args": ["uber-mcp"] } } }
To let it request rides, set both caps in the server's environment, in your account's currency: the most one ride may cost and the most everything it books may cost in any 24 hours, for example
claude mcp add uber -e UBER_MAX_FARE="USD 80" -e UBER_MAX_FARE_24H="USD 200" -- uvx uber-mcp, or"env": { "UBER_MAX_FARE": "USD 80", "UBER_MAX_FARE_24H": "USD 200" }beside"args"(Booking safety).Ask. "How much is an Uber from home to the airport right now?", "Book the cheapest one", "Where is my driver?", "What did my last three rides cost?".
These commands run the latest release from PyPI (uber-mcp); write
uber-mcp==X.Y.Z to stay on a release, or --from git+https://github.com/benjamin-di/uber-mcp-server for the latest code.
Related MCP server: Beckn Mobility MCP Server
Tools
Tool | What it does |
| No query: your saved places (Home and any you named, with their labels). With a query: Uber's place search around |
| Every ride option Uber offers for the trip right now: name, tier, seats, live |
| Preview a native future reservation; after approval, call again with only |
| Read Uber's reservation status, exact pickup time and zone, driver assignment and eventual trip ID. |
| Preview the fee for this reservation; after approval, cancel with the same ID and token. |
| Without |
| The current ride with separate pickup and destination arrival estimates, when checked, driver (name, rating), car/plate, PIN, fare and stops. Only |
| Without |
| Upcoming (first page) and past trips, newest first. Optional past-ride details include category, receipt vehicle, route and times. Pages back with |
| One trip: status, fare, category, receipt vehicle description/year when available, driver, pickup/drop-off/stops, times, distance, duration and route map. |
| The signed-in rider: first name, rating, sign-up country, completed trips, Uber One, payment methods (id, name, type, which one the app uses), Uber Cash, money owed, and the server's booking caps and 24-hour spend. |
| Sign-in state ( |
| The authenticated My connections link, where the owner starts sign-in to their own Uber account (Signing in with a link). Its confirmation annotations stay unchanged; returning the link starts and replaces nothing. |
A pickup or drop-off can be a saved place's label (Home), a place id from uber_places (Google place ids such as
ChIJ..., so ids from a Google Maps tool work too), lat,lng, or free text (Uber's top match, echoed back with
alternatives: check it). Airports list their terminals; pass a terminal's lat,lng to be set down there.
A price is {"display": "...", "cents": 4250, "currency": "USD", "kind": "fixed"} with Uber's own display string:
fixed: Uber's upfront price, held for a few minutes (quote_expires_at).range: a metered taxi. The meter decides the fare;centsis the range's high end andlow_centsthe low end.estimate: neither of the above.
Options marked reserve_only need a future Reserve quote before they can be booked. Caps and spend are
{"cents": 8000, "currency": "USD", "display": "USD 80.00"}. Errors are {"error": {code, next_step, retryable}},
and the next_step text tells the assistant what to do (Troubleshooting).
When will my car arrive? When will we get there?
Call uber_ride_status() for a fresh snapshot. The two estimates are separate:
Before pickup,
trip.pickup_arrivalreportson_the_way, witheta_minutes,estimated_atand Uber's display text when available.arrivedmeans Uber reports that the car is already at pickup. Searching for a driver and future rides do not imply that a car is on the way.Once the trip is underway,
trip.destination_arrivalreportsin_progress, witheta_seconds,estimated_atand display text when available. The pickup state becomespicked_up; no pickup countdown is shown.
trip.checked_at records when the server read the estimate. Arrival timestamps use ISO 8601 UTC with an explicit
offset; assistants can present them in the rider's local time. These are changing estimates, refreshed on each
call. Missing estimates are omitted, not replaced by zero; a genuine zero estimate does not prove arrival.
Uber's hidden or next-stop estimates are not labelled as final-destination arrivals. No automatic polling or
notifications are started. Existing pickup_eta and arrive_at aliases now appear only in their applicable phase.
Reviewing past rides
Use uber_trips(include_details=true, timezone="Europe/Paris") to review routes, categories and times together.
Follow next_cursor for older rides, or use uber_trip(id, timezone=...) for a single ride. Detail mode adds one
paced read per past ride; the default list stays lightweight. If a trip has disappeared, its summary remains with
details_error; sign-in, rate-limit and other upstream failures stop the call.
product is the ride category. vehicle.description and vehicle.year come directly from Uber's receipt when
available; the description can simply repeat the category. History does not reliably expose make, model or plate.
pickup, dropoff and stops are Uber's reported route addresses. times.begin_at and times.dropoff_at use
ISO 8601 with explicit offsets in the requested IANA time zone (UTC by default); the original text remains in
started_at and ended_at. Missing or unrecognizable times are omitted from times rather than guessed.
For cancelled or upcoming trips, the reported beginning can be the requested/scheduled time, so
times.meaning says reported_times_not_proof_of_travel; it is completed_trip for completed trips.
Reserve a future ride
Ask your assistant to reserve a ride for an exact pickup date and time, for example from Example Hotel to
Example Airport at 2027-01-12T06:30:00+01:00, time zone Europe/Paris. The assistant first calls
uber_ride_options with both pickup_at and timezone, which returns Uber's future Reserve quote, available
products and the current reservation terms. Without those arguments it still returns immediate fares.
To book, uber_reserve_ride first takes the journey, product, exact pickup time, IANA time zone and optional payment
and returns a preview. Nothing is booked. Review the full date, time, time zone, resolved locations, fare, payment
and cancellation terms. After your approval, the assistant calls uber_reserve_ride with only its confirm
token. The server rechecks eligibility, the stored payment, price, terms, caps and nearby reservations before sending
Uber's native Reserve request. A changed price or policy requires a new preview and approval. No timer on this
server dispatches the car: Uber holds the reservation even if this server is offline at pickup time.
uber_trips includes upcoming trips and their reservation_id where Uber supplies a reservation link. Use
uber_reservation(id) to read its authoritative status. Reservation acceptance and driver assignment are separate:
a reservation does not guarantee a driver. To cancel, use uber_cancel_reservation(id) to preview the current fee,
then the same ID and confirm token after approval. Unknown fees stop cancellation; changed fees or terms require
another preview. Cancellation works while booking is frozen. Freezing does not cancel existing reservations.
Booking uses the existing caps: the rolling 24-hour cap counts authorizations when they are made, including future
reservations, rather than the day the journey takes place. Cancelled bookings still count. An uncertain submission
keeps a financial hold even after 24 hours and prevents further booking on that account until resolved. The server
never resubmits it automatically. uber_status.booking lists known reservations and unresolved attempt IDs.
For reservations made here, the running server checks status every six hours, every 15 minutes within a day of pickup, and every five minutes within two hours. These checks share Uber's request budget and pause. Status records show the last observation and attention flags (unavailable status, failed reservation, or no driver assigned within 30 minutes of pickup); these are observations, not a dispatch guarantee. Polling is coordinated across processes. If no terminal outcome is verified within 24 hours after pickup, automatic polling stops and status requires manual verification. No notification channel, reminder, calendar entry or replacement booking is created automatically. An operator may use these fields with their own notification system. App-created reservations can be read, but are not automatically registered for background monitoring.
Scope and recovery
The first Reserve implementation supports a single destination, native Reserve, and products with an upfront quote. Airport drop-offs are supported where Uber offers them. Airport pickups, metered/estimated fares, third-party products, extra consent screens, recurring rides, flight tracking and reservation edits are not bookable through this flow. Booking windows and terms come from Uber; the server does not assume one worldwide cancellation policy. Ambiguous repeated daylight-saving hours are rejected because Uber's quote represents the pickup as offset-free local time. An existing reservation within one hour of the requested pickup blocks a new one as a conservative duplicate check; this is not a journey planner or a guarantee that more widely separated trips cannot overlap.
A lost response or process crash can leave an uncertain attempt. Inspect Uber's upcoming trips independently before resolving it. The operator can list attempts and either bind a verified reservation with the same pickup instant or explicitly attest that no reservation was accepted:
uber-mcp admin reservation list
uber-mcp admin reservation resolve ATTEMPT --reservation-id RESERVATION_UUID
uber-mcp admin reservation resolve ATTEMPT --not-bookedThese commands take --account ID. Resolution never submits a booking or cancellation. --not-booked releases the
hold on the operator's explicit attestation; absence from a single list response is insufficient evidence. No
exactly-once guarantee is claimed: the rider web flow exposes no verified client idempotency key. A corrupt ledger
stops booking and needs operator recovery rather than silently resetting its financial history.
Booking safety
Enforced in code (src/uber_mcp/booking.py, the only module that can send a ride request or cancellation) and pinned
by tests/test_safety.py and tests/test_booking.py:
Off unless you set both caps. Without
UBER_MAX_FARE(one ride) andUBER_MAX_FARE_24H(everything booked through this server in any 24 hours),uber_request_rideanswersbooking_disabledbefore asking Uber anything. Both use the same currency, and the per-ride cap cannot be above the 24-hour one; one without the other refuses to start.Preview, then confirm. The first call only previews and returns a
confirm_token. The token works once, for 10 minutes, and only with exactly the arguments of its preview. The tool descriptions and the server's instructions tell the assistant to show the preview and wait for the person's explicit yes; the tools are marked destructive, so clients that ask before such calls do.Never above the approved price. At confirm the server asks Uber for a fresh price for the same option. If it is higher, or in another currency, nothing is booked and a fresh preview comes back (
price_rose) for the person to approve. A lower price books. For a metered taxi the approved price is the range's high end; the meter decides. For anestimateUber has not committed to a price, so the final fare can differ from the approved one.Within the caps. The ride's price must fit the per-ride cap and, together with the rides this server booked in the last 24 hours, the 24-hour cap, in the caps' currency (
over_cap, with the reason). Cancelled rides still count; rides booked in the Uber app do not.One ride at a time. A preview or a confirm while a ride is active answers
trip_active.No blind retries. When a request was sent but its answer is lost, the result is
outcome_unknown: the assistant readsuber_ride_status, and the server never repeats a request on its own.Freeze.
uber-mcp admin freeze [REASON]stops all booking at once and drops every pending preview;uber-mcp admin unfreezeresumes within the caps. Cancelling still works while frozen.Audit log. Every confirm, booked or not (refused with the reason, started, failed, refused by Uber, succeeded; cancels too), is appended to
audit.jsonlwith the product, the price and the trip id, never the places.uber-mcp admin audit [-n N]shows the latest.Only booking. No endpoint for payment methods, tips, ratings, profiles, saved places, reservation edits, Uber Eats or account settings exists in the code.
Other safety
Only Uber. Requests go only to
m.uber.comandriders.uber.com, and only with the GraphQL operations listed insrc/uber_mcp/uber.py; a redirect is never followed.Gentle. One request at a time, about one a second, a daily request budget, and a pause of 5 minutes (30 when it repeats within two hours) whenever Uber pushes back.
Your account only. The server acts for the signed-in rider (with several accounts, for the account the request is for, never another). Every read of the account checks that it is still the rider who signed in. Place names, driver names and trip descriptions are treated as data, not instructions.
Privacy
Everything stays on the computer that runs the server, in its state folder (~/.local/state/uber-mcp on Linux,
~/Library/Application Support/uber-mcp on macOS, %LOCALAPPDATA%\uber-mcp on Windows, /state in the container;
UBER_STATE_DIR overrides it):
File | What it holds |
| Your Uber sign-in (cookies), the browser identity it was made with, your account id and first name. Treat it like a password. With |
| The sign-in window's browser profile ( |
| Today's request budget, any pause, unresolved errors, keep-alive and canary results. |
| Pending previews (including resolved Reserve locations, payment and terms, for 10 minutes), booking authorizations, durable reservation attempts and financial holds, monitoring observations and the freeze. |
| Every booking and cancellation attempt (above). |
| Each further account (Accounts): its own |
Nothing is sent anywhere except Uber. What a tool returns (places, prices, the driver's name, the plate, the PIN)
goes to your assistant, like anything else you ask it. Logs (stderr) have one line per tool call with its name,
outcome and duration, never its arguments, cookies or Uber's error text. The account read includes your email
address and phone number (Uber's own query asks for them); the server drops them. uber-mcp status shows only the
first letter of the account's name. uber-mcp logout deletes the session and the browser profile.
Signing in
uber-mcp login opens Uber's sign-in page in your installed Google Chrome, using a separate profile in the state
folder. You do every step yourself; nothing is clicked or typed for you, and the window shows only Uber's pages (and
Google's or Apple's, for their sign-in buttons). Once Uber shows its rides page, the window opens Uber's trips site
once (it signs in there through Uber's own single sign-on), reads your account on both with the same cookies, saves
the session and closes. A running server picks up the new session with its next call.
No Chrome? Run
uvx --from "uber-mcp[login]" patchright install chromium, thenuvx --from "uber-mcp[login]" uber-mcp login --browser chromium.Uber decides how long a session lasts. The server reads both of Uber's sites every 4 hours (
UBER_KEEPALIVE_SECONDS), which lets Uber renew its short-lived cookies;uber_statusshows when each sign-in cookie expires. When the session ends, tools returnsession_expired: sign in again.uber-mcp statusshows whether the saved session is signed in, without asking Uber anything.Every sign-in raises the session's
generation; a newer sign-in always wins over cookies another process is still writing back.
On a server: the login service
A server has no screen for the sign-in window. The login browser image (ghcr.io/benjamin-di/uber-mcp-login-browser)
runs Uber's sign-in page in a Chromium next to the server and shows it to the person through
noVNC in their own browser. Nothing on the sign-in is automated there either.
Run the service beside the server on a private network, with the same UBER_LOGIN_TOKEN
(32 or more characters) on both and UBER_LOGIN_URL on the server. Hosted owners use
the authenticated My connections page described below. The service verifies both Uber
surfaces and the retained rider binding before the application seals accepted credentials
with UBER_SESSION_KEY.
The login API and operator CLI are privileged local administration. Keep raw /logins
and operator /view routes private; a per-window token is not a replacement for hosted
owner OIDC. A loopback-only maintenance port must not become a second public login entry.
Signing in with a link
Human OIDC authorizes account management only. The MCP gateway (for example Agentgateway) separately authenticates clients/workloads and applies audience, scope and tool ceilings; Uber's native rider session and booking rules are a third boundary. Connecting Uber never approves an agent or a paid ride. Pocket ID is one compatible OIDC provider, with no vendor-specific requirement. See permission boundaries and the remaining project checks.
With the login service and a public address (UBER_PUBLIC_URL, the address your reverse proxy serves the server at,
e.g. https://example.com/uber when /mcp is https://example.com/uber/mcp), people sign in without the operator:
they ask their assistant to connect Uber, the assistant calls uber_connect (the not_signed_in and
session_expired errors point it there) and gives them the link, and they sign in on Uber's own page in their
browser, phone or computer. The page names the account it connects and opens Uber's sign-in only when the person
continues (so a chat app's link preview starts nothing). Hosted sign-in requires the account owner's
OIDC browser identity, including links created by an assistant. Configure the identity client and account bindings
before upgrading; Connections setup and recovery lists the routes, required settings and
persistent disconnect controls. My connections also lets the owner reconnect without asking an assistant.
For the caller's account only. The link is made for the account the request is for (the default account, or the one the trusted header names). It returns My connections without starting or replacing an attempt. Only an authenticated owner choosing Connect creates an attempt; at most 6 owner starts are allowed per account an hour.
One sign-in, 20 minutes.
<UBER_PUBLIC_URL>/connect/<id>(192 random bits) works until a sign-in succeeds or 20 minutes pass, whichever is first. Reload resumes an existing window; an explicit retry can open a new one, up to 4 times. Its pages are never cached (Cache-Control: no-store) and send no referrer. Requests for ids that do not exist are counted per address (fromX-Forwarded-For, which the proxy must set): after 20 in ten minutes that address gets 429 instead of 404 (a real link keeps working).It only puts a session in. Once the login service has proven the sign-in, the server stores it as that account's session only after independently verifying a private staged candidate with Uber; the page shows only the first letter of the rider's name. Nothing under
/connectshows or returns a session. A sign-in as a different Uber rider than the account already has (even an expired one) is refused, and so is a rider another account on this server holds; the operator can still sign an account in withuber-mcp admin login.The authenticated owner controls it.
/connect/...is outside the MCP bearer boundary, but its page, calls, noVNC assets and WebSocket require the account owner's browser session. The id alone authorizes nothing. Forward only the exact browser routes documented in Connections, preserve cookies and Origin, and strip untrusted bearer and account headers./mcpkeeps its existing admission checks.Pasting works. Ctrl+V (Cmd+V) in the window types the clipboard's text into Uber's page (a small add-on to noVNC's viewer from signin-window, the library the sign-in window and its links are built on; up to 1000 characters, characters the window's keyboard has, which covers ASCII). On a phone, noVNC's keyboard button opens the phone's keyboard, which pastes as usual.
Passkeys do not work in a remote window: sign in with a code or a password.
Without the login service, sign in with uber-mcp login on a computer with a screen and copy its session.json into
the server's state folder; the server adopts it on its next call. A server with UBER_SESSION_KEY reads only
session.bin: sign in with the same key set (UBER_SESSION_KEY=... UBER_STATE_DIR=... uber-mcp login) and copy that.
Running it as a server
For remote clients (claude.ai, ChatGPT and the Claude and ChatGPT apps reach connectors over HTTPS), run it over streamable HTTP. It refuses to start without a bearer token:
docker run -d --name uber-mcp -p 127.0.0.1:8000:8000 --read-only --tmpfs /tmp \
-e MCP_BEARER_TOKEN="$(openssl rand -hex 32)" \
-e UBER_SESSION_KEY="$(openssl rand -base64 32)" \
-v uber-state:/state \
ghcr.io/benjamin-di/uber-mcp-server:latestLike this it cannot book; add -e UBER_MAX_FARE=... -e UBER_MAX_FARE_24H=... to let it
(Booking safety). Keep the bearer and the session key: a new key cannot read a session sealed with
the old one (session_invalid, sign in again). Or run MCP_BEARER_TOKEN=... uvx uber-mcp serve --host 127.0.0.1 --port 8000. The MCP endpoint is /mcp; /health is open for health checks (the image's
HEALTHCHECK runs uber-mcp health). Put it behind your own HTTPS reverse proxy to reach it from outside, and give
clients the bearer (Authorization: Bearer <token>).
The server image (amd64 and arm64) runs as uid 1000 on a read-only root filesystem: it writes only to /state, which
holds everything in Privacy, and to a /tmp tmpfs. With the login service, as a compose file:
services:
uber-mcp:
image: ghcr.io/benjamin-di/uber-mcp-server:latest
read_only: true
tmpfs: [/tmp]
ports: ["127.0.0.1:8000:8000"]
volumes: [uber-state:/state]
environment:
MCP_BEARER_TOKEN: ${MCP_BEARER_TOKEN}
UBER_SESSION_KEY: ${UBER_SESSION_KEY}
# To let it book: both caps, in your account's currency (Booking safety).
# UBER_MAX_FARE: USD 80
# UBER_MAX_FARE_24H: USD 200
UBER_LOGIN_URL: http://uber-mcp-login:8080
UBER_LOGIN_TOKEN: ${UBER_LOGIN_TOKEN}
uber-mcp-login:
image: ghcr.io/benjamin-di/uber-mcp-login-browser:latest
ports: ["127.0.0.1:8766:8080"]
environment:
UBER_LOGIN_TOKEN: ${UBER_LOGIN_TOKEN}
volumes:
uber-state:The login image (amd64) runs as uid 1000, keeps nothing (each sign-in gets a throwaway browser profile that is
deleted when it ends) and refuses to start without UBER_LOGIN_TOKEN. It can stay stopped between sign-ins.
Accounts
One server can keep several Uber accounts apart, for example one per member of a household, behind an authenticating reverse proxy that knows who is calling. Each account has its own sealed session, booking caps, ledger, audit log and errors; Uber's pacing, the daily request budget and the pause after pushback are shared, because Uber sees one client.
The default account is the server's own state folder, with the caps from
UBER_MAX_FARE/UBER_MAX_FARE_24H: a single-account server needs nothing new, and its existing session and ledger keep working. Name it withUBER_DEFAULT_ACCOUNT(defaultdefault) if the proxy sends that name for it.Further accounts live in
accounts/<id>/(ids are 1-32 lower-case letters, digits or dashes). A new account has no caps, so it can look but not book until the operator sets them.Which account a request is for comes from a header the proxy sets, named by
UBER_TRUSTED_ACCOUNT_HEADER(unset: every request is the default account's). It is read only on requests that carry the server's bearer, so only the proxy may holdMCP_BEARER_TOKEN, and the proxy must remove any copy of that header a client sends. A request without the header is the default account's; one whose header names an account that is not set up (or names it twice, or malformed) getsaccount_not_connectedand is never served from another account. Over stdio there is no header: always the default account.Confirm tokens belong to the account that previewed them: a token from one account is
confirm_invalidon any other.
docker exec uber-mcp uber-mcp admin account add alex # read-only for now
docker exec -it uber-mcp uber-mcp admin login --account alex # or the person asks their assistant (uber_connect)
docker exec uber-mcp uber-mcp admin account caps alex --max-fare "USD 40" --max-fare-24h "USD 100"
docker exec uber-mcp uber-mcp admin account list # signed in or not, and the caps
docker exec uber-mcp uber-mcp admin account remove alex --yes # deletes its session, ledger and audit logCaps (and a removal) apply on the server's next call; no restart. status, admin audit, admin freeze and
admin unfreeze take --account ID too; admin freeze without it freezes every account. uber_status and
uber_account name the caller's account in account_id.
Configuration
The server (uber-mcp):
Variable | Default | |
| required for | one or more tokens (comma-separated, at least 16 characters each), so one can be rotated while the other still works |
| per-user folder (see Privacy); | the session, budget, pause, booking ledger and audit log |
| unset | 32 random bytes, base64: the session is stored sealed (AES-GCM) as |
| unset | the most one ride may cost, a currency code and an amount ( |
| unset | the most all rides booked through this server in any 24 hours may cost, same currency; booking is off without it |
| 1500 | Uber requests per day (resets 00:00 UTC) |
| 14400 | how often an idle session is refreshed by reading both of Uber's sites (60 to 86400) |
| unset | the login service on a private network, a name and port such as |
| unset | the login service's bearer, 32 or more characters; required with |
|
| where the person opens the login service's view page (above) |
| required for browser sign-in | fixed issuer/client/group and administrator-owned account mapping; configuration |
| unset | the HTTPS address people reach this server at (the parent of |
| unset | the header your authenticating proxy sets to name the caller's account (Accounts); only for a bearer no one but the proxy holds |
|
| the id of the account kept directly in the state folder |
| INFO |
The login service (ghcr.io/benjamin-di/uber-mcp-login-browser, python -m uber_login):
Variable | Default | |
| required | the bearer |
| 1 | sign-ins at the same time |
| 20 | how long a sign-in may take before it is ended |
| 8080 | |
|
| noVNC's files |
|
| the virtual display and remote-desktop programs |
Troubleshooting
Code | What to do |
| The assistant passed something malformed; the text says what. |
| Run |
| Uber ended the sign-in: sign in again (as above). |
| The saved session cannot be read (damaged, sealed under another |
| Uber pushed back (a 429 or a challenge page); calls resume after the pause ( |
| Today's request budget is spent; it resets at 00:00 UTC ( |
| Another Uber request was still running after 30 seconds; retry. |
| Uber or the network failed; retry in a minute. |
| Uber changed its web API (a renamed field, a moved endpoint). Check for a newer release, or open an issue; |
| Uber found no place: be more specific, or pass a saved place's label, a place id or |
| Uber offers no rides for this trip right now; try later or from another pickup. |
| That option is not offered now, or it is reserve-only; pick one from |
| No payment method matches; |
| Booking is off: set both |
| The price is above the per-ride cap or the 24-hour total, or in another currency than the caps ( |
| The price went up since the preview; nothing was booked. The answer holds a fresh preview for the person to approve. |
| The token is unknown, used, expired (10 minutes), for other arguments, or was dropped by a freeze: preview again. |
| A ride is already active; it must end or be cancelled first. |
| There is no ride to cancel. |
| Uber did not accept the request ( |
| A request or cancellation was sent but the answer was lost: check |
| The request named an account this server does not have (or a malformed one): add it and sign it in (Accounts). Nothing was done. |
| This server makes no sign-in links ( |
| More than 6 links for this account in an hour: use the newest one, or wait. |
| A bug; retry once, and open an issue if it repeats. |
How it works
Uber has no public rider API for this, so the server speaks GraphQL to the endpoints Uber's rider website uses, over
plain HTTP, with the cookies of a browser session you signed in to and the GraphQL documents Uber's own web apps
send. docs/uber-web-api.md records what is known about those endpoints;
docs/DESIGN.md explains the decisions. When Uber changes its web API, calls fail with
schema_changed until the server is updated.
Development
See CONTRIBUTING.md. Tests never contact Uber.
Credits
Built on what crafter-station/uber-cli worked out about Uber's rider
web API: scripts/sync-operations.py is a port of its script that reads the GraphQL documents from Uber's own web
bundles, and the price and ride request variables follow its code (MIT; THIRD_PARTY_NOTICES).
Design ideas also came from AriOliv/uber-mcp (MIT).
License
MIT.
Available Tools
13 toolsuber_accountAccountARead-onlyIdempotent
The signed-in rider: first name, rating, completed trips, Uber One, payment methods (id, name, type, which one the app uses), Uber Cash, any money owed, and this server's booking caps.
Inputs: no named parameters. Returns: object
uber_cancel_reservationCancel a reservationADestructive
Cancel a specific future reservation. Without confirm: preview the reservation and current cancellation fee. After approval: same id and confirm token. Changed terms require a new preview; cancellation remains available while booking is frozen. Never retry an unknown outcome without checking Uber.
Inputs: id (required), confirm. Returns: object
uber_cancel_rideCancel the rideADestructive
Cancel the current ride, in two calls. Without confirm: the ride and Uber's cancellation notice (any fee) with a confirm_token; nothing is cancelled. With confirm (after the person's yes): cancels it.
Inputs: confirm. Returns: object
uber_connectSign-in linkA
The authenticated My connections link. Give the person the url and nothing else. The account owner starts their own Uber sign-in from that page; asking for this link starts, replaces and cancels nothing. Use it when a tool says not_signed_in or session_expired, or when the person asks to connect Uber.
Inputs: no named parameters. Returns: object
uber_placesPlacesARead-onlyIdempotent
The rider's saved places (no query: Home and any the rider named, with their labels), or Uber's place search (query; around near, else around Uber's guess of the rider's position). Each place has an id (a Google place id) to pass as a pickup or drop-off, a name and address, and for airports the terminals per airline.
Inputs: near, query. Returns: object
uber_request_rideRequest a rideADestructive
Request a real Uber ride, in two calls. Without confirm: a preview with the current price, the places, the payment method and a confirm_token; nothing is booked. With confirm (after the person's explicit yes to that preview, same arguments): books it, unless the price rose (a fresh preview comes back instead) or a cap would be passed. Sends a car and charges the payment method.
Inputs: option (required), pickup (required), dropoff (required), confirm, +1 more. Returns: object
uber_reservationReservation detailsARead-onlyIdempotent
Read a reservation by reservation_id (from booking or uber_trips.upcoming). Returns Uber's status, pickup time/zone, driver assignment and trip ID. Missing data is not proof of cancellation.
Inputs: id (required). Returns: object
uber_reserve_rideReserve a future rideADestructive
Native Uber Reserve. First call: pickup, dropoff, option, exact ISO pickup_at with offset, IANA timezone, optional payment. Returns a preview only. Show the full date/time/zone, route, fare, payment and terms and wait for approval. Second call: ONLY confirm=; submits that stored proposal after fresh checks. If the price rose, nothing is submitted; review the returned fresh preview and obtain approval again. Never retry an unknown outcome. Uber holding a reservation does not guarantee a driver. No flight tracking, recurring rides, specialty products or automatic replacement bookings.
Inputs: option, pickup, confirm, dropoff, +3 more. Returns: object
uber_ride_optionsRide options and pricesARead-onlyIdempotent
Every ride option Uber offers for this trip right now: name, tier, seats, live price (fixed upfront price, or a range for a metered taxi), pickup ETA and arrival time, with the pickup and drop-off as Uber matched them (check them; free-text matches list alternatives). For a future pickup supply pickup_at AND timezone: returns native Reserve prices and terms, never current fares. Read-only; use uber_request_ride for now, uber_reserve_ride for future pickup.
Inputs: pickup (required), dropoff (required), payment, timezone, +1 more. Returns: object
uber_ride_statusLive rideARead-onlyIdempotent
Read a fresh snapshot of the current ride. trip.pickup_arrival gives the car's state, eta_minutes and estimated_at when approaching pickup; arrived means the car is already there. Once OnTrip, trip.destination_arrival gives eta_seconds and estimated_at for destination arrival. checked_at is when the server read the estimate; times use ISO 8601 UTC and estimates can change. Missing estimates are unavailable, never zero. Also driver, car/plate, PIN, fare and stops. state alone when no ride exists. Use this same read-only tool for 'when will my car arrive?' and 'when will we reach the destination?'.
Inputs: no named parameters. Returns: object
uber_statusServer statusARead-onlyIdempotent
Sign-in state (signed_in, generation, when proven, cookie expiry), today's request budget, any pause after Uber pushed back, booking caps and spend, last_error (the newest failure no later success has cleared) and sign_in_links (whether uber_connect can make a sign-in link). check=true adds the cached canary.
Inputs: check. Returns: object
uber_tripTrip detailsARead-onlyIdempotent
One trip: status, fare, ride category (product), receipt vehicle description/year when supplied, driver, pickup/drop-off/stops, distance and duration. times has ISO 8601 begin_at/dropoff_at in the requested zone (default UTC); started_at/ended_at retain Uber's original text. Cancelled/upcoming begin times may be requested/scheduled, never proof of pickup. A receipt vehicle description can just repeat the category; never infer a make, model or plate that Uber did not supply.
Inputs: id (required), timezone. Returns: object
uber_tripsTrip historyARead-onlyIdempotent
Upcoming (first page) and past trips, newest first. Page back with next_cursor. include_details adds each past ride's category, receipt vehicle, route and offset-bearing times in details; costs one extra paced read per past ride. Missing trips have details_error; other errors stop the call. Times on cancelled/upcoming rides may be requested or scheduled times, never proof of travel.
Inputs: limit, cursor, timezone, include_details. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 13 tools
The set is split cleanly along real axes: now vs. future vs. read-only pricing (uber_request_ride / uber_reserve_ride / uber_ride_options), cancel now vs. cancel future (uber_cancel_ride / uber_cancel_reservation), list vs. single trip vs. reservation (uber_trips / uber_trip / uber_reservation), and auth vs. profile vs. server health (uber_connect / uber_account / uber_status). A couple of near-homographs remain — uber_reservation vs. uber_reserve_ride, and uber_status vs. uber_ride_status — where an agent could plausibly reach for the wrong tool before reading the description. Descriptions do explicitly cross-reference and redirect, which rescues most of that overlap.
All tools share a uniform uber_ prefix and snake_case, and there is an implicit and mostly respected convention: verb-led names for mutations (request_ride, reserve_ride, cancel_ride, cancel_reservation, connect) and bare nouns for reads (account, places, trips, trip, status, reservation). The deviations are the noun forms uber_ride_options and uber_ride_status, which mix the noun convention with an extra qualifier, and the confusingly similar reserve_ride/reservation pair.
Thirteen tools for a rideshare domain of this breadth is well-scoped, with each tool owning a distinct action or resource. Nothing looks padded: even the auth and diagnostic tools (uber_connect, uber_status) earn their place because every booking tool can fail with not_signed_in or a cap.
The core lifecycle is covered end to end: discover places, compare products and fares, book now or schedule, poll live trip state, cancel either kind, and review history. The main gaps are post-ride actions — no rating, tipping, receipt/expense retrieval, lost-item or support flows — and no way to modify an existing reservation other than cancel and rebook. These are workarounds rather than dead ends, since cancel+reserve covers the modification case.
Maintenance
Related MCP Connectors
Get date-specific quotes and book private UK airport and cruise-port transfers through your AI assistant. Compare vehicle options, validate flights, retrieve bookings, amend details and cancel with customer confirmation. No registration required to start, subject to service limits; optional API-key and OAuth access for registered integrations. Transfer fares are payable separately and cancellation conditions apply. Live demo and connection instructions: https://ai.airport-pickups-london.com/ Technical documentation: https://mcp.airport-pickups-london.com/docs
Mobility, geocoding and nearby urban services for AI agents.
Read and update your Everway trips and itineraries from any MCP-compatible AI assistant.
Travel tools for AI agents: plan and edit real trips, search stays and tours, import travel videos.
Related MCP Servers
- AlicenseAqualityDmaintenanceAn MCP server that enables AI assistants to book and manage Uber rides, including getting price estimates, requesting rides, checking ride status, and canceling rides.614 npm16ISC
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to search for cabs, view prices, and book rides through the open Beckn Protocol by connecting to Beckn-compliant mobility providers like Namma Yatri and ONDC.-
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with the Uber API for ride management, including requesting rides, obtaining price and time estimates, and tracking active trip status. It supports comprehensive journey features such as viewing ride history, cancelling requests, and rating drivers through a secure OAuth 2.0 integration.MIT
- FlicenseAqualityDmaintenanceAllows AI assistants to browse menus, manage carts, and place orders on Uber Eats through natural language commands.343-