# Let AI run leadgen — Claude Code, claude.ai, and a multi-tenant host

leadgen ships an **MCP server** (`leadgen_maps/mcp_server.py`) exposing these tools:
`leadgen_run`, `leadgen_connect`, `leadgen_status`, `leadgen_doctor`,
`leadgen_fields`. Any MCP-capable AI can call them.

## How destinations work (multi-tenant)
- **Default `to="csv"`** → leads are returned **inline** in the result. They're
  the caller's own data; nothing is written to anyone's account. **Zero setup.**
- **`to="notion"`** → the user connects **their own** Notion via a one-time
  secure page (`leadgen_connect` → open URL → paste their token). The grant is
  tracked per `connect_token`. Tokens stay on the server, never in chat, never in
  an env file you edit.

So **one server + one URL can serve thousands of users**, each isolated.

---

## 🖥️ Claude Code (your computer)
This repo includes `.mcp.json`. Open the folder in Claude Code, approve the
**leadgen** server, then ask: *"Pull 15 gyms in Mumbai, no website."* (Or just
let it run the `leadgen` CLI directly.)

## 🌐 claude.ai (the website) — quick test with ngrok
1. Start the server (on a machine with Chrome + Playwright):
   ```
   python -m leadgen_maps.mcp_server --http
   ```
2. Tunnel it and tell the server its public URL so connect links work:
   ```
   ngrok http 8000
   # copy the https URL it prints, then restart the server with it:
   #   setx LEADGEN_PUBLIC_URL https://<id>.ngrok-free.app   (then reopen terminal)
   #   python -m leadgen_maps.mcp_server --http
   ```
3. claude.ai → **Settings → Connectors → Add custom connector** → paste
   `https://<id>.ngrok-free.app/mcp` (needs a Pro/Max/Team/Enterprise plan).
4. Chat: *"Use leadgen to get 5 cafes in Pune."* → leads come back inline. Want
   them in your Notion? Say *"send them to my Notion"* → Claude calls
   `leadgen_connect`, you open the link, paste your Notion token, retry. Done.

> **ngrok is temporary** — the free URL changes every restart and dies when you
> close it. Fine for testing; use Cloudflare below for permanent multi-user hosting.

---

## 🚀 Permanent, multi-user hosting (Cloudflare Tunnel)
A Cloudflare **named tunnel** gives a *stable* URL on your own domain (e.g.
`https://leadgen.yourdomain.com`). Thousands of users add that **one** URL as
their connector; the multi-tenant server keeps them isolated.

**Prereqs:** a domain on Cloudflare (free plan is fine) + `cloudflared` installed.

```bash
# 1. log in (opens browser, pick your domain)
cloudflared tunnel login

# 2. create a named tunnel (one time)
cloudflared tunnel create leadgen
#    -> writes a credentials json + a tunnel UUID

# 3. route a subdomain to it (one time)
cloudflared tunnel route dns leadgen leadgen.yourdomain.com

# 4. run the leadgen server, told its public URL:
LEADGEN_PUBLIC_URL=https://leadgen.yourdomain.com python -m leadgen_maps.mcp_server --http

# 5. run the tunnel pointing at the local server (keep it running / make it a service)
cloudflared tunnel --url http://localhost:8000 run leadgen
```
Now your permanent connector URL is **`https://leadgen.yourdomain.com/mcp`**.
Share it; every user adds it once and gets their own isolated runs (default CSV,
opt-in their own Notion). Run the server + tunnel on an always-on box (a small
VPS) so it works even when your PC is off — `deploy/` has a Docker image and
`cloudflared` can run as a system service.

**Scaling note:** scrapes are browser-driven and CPU/RAM-heavy; one box handles a
handful of concurrent runs. For real volume, run several server replicas behind
the tunnel (Cloudflare load-balances) and keep per-user `limit` modest.

---

## Security
- Each user's Notion token is held **only on the server** (in memory), keyed to
  their `connect_token`; it's never shown in chat or sent to the AI platform.
- The connect page is served over your HTTPS tunnel. For production, add a real
  datastore with encryption and rotate/expire tokens. Notion/Google **OAuth**
  (so users click "Sign in" instead of pasting a token) is the next upgrade —
  the `leadgen_connect` flow + `/connect` route are already shaped for it.
- Anyone with your connector URL can run scrapes (default CSV only). Gate it with
  Cloudflare Access if you want to restrict who can connect.
