# Quickstart: first call to WhatsDo MCP | WhatsDo Docs

URL: https://whatsdo.ai/docs/quickstart

Skip to contentDocumentationTools reference

Sign inGet API key

Search the docs menu

Get started
- Overview
- Quickstart
- Connect your agent
- Keys and sign-in

Guides
- Book a table
- Shortlist restaurants
- Café and a walk
- Massage, salon, yoga
- Local market signals

Reference
- Tools
- Booking statuses
- Limits
- Errors and fixes

# Quickstart

Connect to the WhatsDo MCP server and make your first call.

## Server address

WhatsDo is a hosted MCP server. Clients that speak MCP over Streamable HTTP can use it. The server is stateless: each request stands on its own.

https://app.whatsdo.com/mcp/Copy

Keep the trailing slash. /mcp without it answers with a redirect, and not every client follows a redirect on POST.

## Sign in

- Claude, Claude Code and ChatGPT: add the server address. The client opens a WhatsDo sign-in. No key to copy.
- Cursor, Gemini CLI and Codex: sign-in or an API key. See Connect your agent.
- Scripts, servers and VS Code: get an API key, copy it once and send it as Authorization: Bearer <key>. Tick bookings:write if your agent books. Or use the setup page: it creates a key that can book.Bookings are made as the signed-in WhatsDo account. Name and phone come from that account’s profile.

## First call

A booking request takes four calls, in this order.

- 1search with the person’s words, a San Francisco location, bookable_only: true and a limit of 3 to 5. Keep the id and booking_source of the place they pick.
- 2get_booking_requirements with that id. Ask the person only for fields that are missing.
- 3book after the person said yes to the place, date, time and party size. Booking is in Beta.
- 4my_bookings to read the status. Nothing is pushed to you.Try the first call with cURL:

bash

```
curl https://app.whatsdo.com/mcp/ \
  -H "Authorization: Bearer $WHATSDO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"search",
                 "arguments":{"query":"asian dinner highly rated",
                              "location":"San Francisco, CA",
                              "bookable_only":true,"limit":3}}}'
```

The reply can come as plain JSON or as an event stream. Read result.structuredContent when it is there, otherwise parse the JSON text in result.content[0].text.

## Full example in Python

One file that runs the whole sequence: initialize, search, then, if you pass a time, get_booking_requirements, book and polling my_bookings until the status settles. It handles both reply formats and prints only safe booking fields. Set WHATSDO_API_KEY first.

python

```
# Python 3.11+, pip install httpx
# Search:          python whatsdo_flow.py
# Search and book: python whatsdo_flow.py 2026-10-09T19:00:00-07:00   (writes a real booking)
import json, os, sys, time
import httpx

MCP_URL = "https://app.whatsdo.com/mcp/"
HEADERS = {"Authorization": f"Bearer {os.environ['WHATSDO_API_KEY']}",
           "Content-Type": "application/json",
           "Accept": "application/json, text/event-stream"}
SAFE = ("place_name", "status", "date_time", "party_size", "confirmation_number", "message")
http = httpx.Client(timeout=120.0)
next_id = 0


def rpc(method, params=None):
    global next_id
    next_id += 1
    resp = http.post(MCP_URL, headers=HEADERS,
                     json={"jsonrpc": "2.0", "id": next_id, "method": method, "params": params or {}})
    resp.raise_for_status()
    if resp.headers.get("content-type", "").startswith("text/event-stream"):
        # The reply is the data: event whose id matches the request.
        events = [json.loads(l[5:]) for l in resp.text.splitlines() if l.startswith("data:")]
        msg = next((e for e in events if e.get("id") == next_id), events[-1])
    else:
        msg = resp.json()
    if "error" in msg:
        raise RuntimeError(msg["error"])
    return msg["result"]


def tool(name, arguments):
    result = rpc("tools/call", {"name": name, "arguments": arguments})
    texts = [c.get("text", "") for c in result.get("content", []) if c.get("type") == "text"]
    if result.get("isError"):
        raise RuntimeError(" ".join(texts))
    if isinstance(result.get("structuredContent"), dict):
        return result["structuredContent"]
    return json.loads(texts[0])


init = rpc("initialize", {"protocolVersion": "2025-06-18", "capabilities": {},
                          "clientInfo": {"name": "my-agent", "version": "0.1"}})
HEADERS["MCP-Protocol-Version"] = init["protocolVersion"]
http.post(MCP_URL, headers=HEADERS, json={"jsonrpc": "2.0", "method": "notifications/initialized"})

found = tool("search", {"query": "asian dinner highly rated", "location": "San Francisco, CA",
                        "bookable_only": True, "limit": 3})
results = found.get("results", [])
if not results:
    sys.exit("No matches. WhatsDo search covers San Francisco; new cities are available on request.")
for r in results:
    print(r["name"], r.get("rating"), r.get("price"), r["id"])
if len(sys.argv) < 2:
    sys.exit(0)

# Only after the person agreed to the place, date, time and party size.
place = results[0]
needs = tool("get_booking_requirements", {"item_id": place["id"]})
if not needs.get("available"):
    sys.exit(f"{place['name']} can't be booked here. Phone: {place.get('phone')}")
booking = tool("book", {"item_name": place["name"], "item_id": place["id"], "date_time": sys.argv[1],
                        "party_size": 2, "source": place["booking_source"]})
rid, status = booking["reservation_id"], booking["status"]

deadline = time.monotonic() + 300
while status == "pending" and time.monotonic() < deadline:
    time.sleep(30)
    rows = tool("my_bookings", {"limit": 10}).get("bookings", [])
    row = next((b for b in rows if b.get("reservation_id") == rid), None)
    if row:
        booking, status = row, row["status"]

# Never print guest email, phone, user id or session links.
print({k: booking.get(k) for k in SAFE})
```

book writes a real booking as the key’s account. Run the booking path only for a place, date and time the person agreed to.

## Next

- Connect your agent
- Tools
- Booking statuses
- Limits

On this page

- Server address
- Sign in
- First call
- Full example in Python
- NextCopy page

© WhatsDo

## Product

MCPPlacesBookingPayments

## Build

ConnectDocsUse cases

## WhatsDo

For businessesTalk to usPrivacy policyTerms of serviceCookie policySite map
