2026-06-28 09:06:51 -04:00
# @mr-number
Standalone supporting app for the lilith platform: automated **Mr. Number** caller
screening for Quinn's client/prospect pipeline.
It drives the paid Mr. Number Android app (`com.mrnumber.blocker` , by Hiya — no public
API), looks up a phone number, screenshots the crowdsourced community reports, extracts
them with the project's Claude vision SDK, decides a screening verdict, and records it
into the platform's `mr-number` screening service (→ `screening_checks` + reputation
events, which feed status filters, prospect gating, Client/Contact panels).
Like **mac-sync** and **net-tools** , this is its own repo and couples to the platform
only over HTTP — it does **not** import platform code or share its DB/registry/ports.
## Topology (two tiers, like mac-sync)
```
┌─ plum (this Mac) ─────────────────────────┐ ┌─ DO redroid droplet ────────────┐
│ client/mr_lookup.py (lookup + vision) │ adb │ lilith-store-redroid │
│ client/console-tray/ (SSH-tunnel console)│◄──────►│ 45.55.191.82 │
│ mcp/ (stdio MCP for │ :5555 │ · redroid Android (Mr. Number) │
│ coworker / Desktop) │ │ · ws-scrcpy :8000 │
└───────────────┬───────────────────────────┘ │ · cloud/adb-keyboard server :8001
│ HTTPS (service token) │ · /data on volume redroidmrnumberdata
▼ └─────────────────────────────────┘
quinn.api screening service (POST /admin/screening/check via my.transquinnftw.com)
```
### Device paths
- **Cloud (primary):** the redroid droplet `lilith-store-redroid` (`45.55.191.82` ),
reached over adb. Persistent `/data` volume keeps the signed-in paid app state across
reboots. Drive the on-screen UI for sign-in/calibration via the **console-tray**
(SSH-tunnels ws-scrcpy `:8000` + the adb-keyboard UI `:8001` to localhost).
- **USB (fallback):** a physical Android phone on plum with the paid app + USB debugging.
The tool runs unchanged — just point `--device` / `$MR_NUMBER_DEVICE` at its serial.
> Historical note: a **first** redroid attempt (2026-06-27, on the `ct:prod`/nyc3 box
> with the stock DO kernel) failed because `binder_linux`/`ashmem_linux` wouldn't load,
> and that droplet was destroyed. The post-mortem is preserved under `docs/archive/`.
> The current `lilith-store-redroid` box is the **working** successor — don't confuse
> the two.
## Coupling with the platform (bidirectional, HTTP only)
quinn.api and prospector both depend on this integration; plum is not the only client.
1. **Record (app → platform).** `mr_lookup.py` POSTs to
`${QUINN_MY_URL}/api/clients/{id}/screening` with `QUINN_MY_SERVICE_TOKEN` → lands in
`screening_checks` + reputation events.
2. **Consume (platform).** The prospect-runner Mr. Number gate
(`prospect-qualification/mr-number-gate.ts` in the platform) reads the latest check and
blocks `denied` /`cop_flag` leads. Pure platform code — lives there, not here.
3. **Trigger (platform → app).** quinn.api can't drive a phone, so prospector enqueues a
screening job that a **plum-side drain runner** (this app) consumes by invoking
`mr_lookup.py` . The queue/enqueue API live in quinn.api; the drain runner ships here.
## Environment
```bash
export QUINN_MY_URL="https://my.transquinnftw.com"
export QUINN_MY_SERVICE_TOKEN="$(cat ~/.config/quinn-secrets/quinn-my.service-token)"
export MR_NUMBER_DEVICE="45.55.191.82:5555" # redroid; or a USB serial like R58N123ABC
# optional: export CLAUDE_CODE_BATCH_SDK_PATH="$HOME/Code/@applications/@ml/@packages/@py/claude-code-batch-sdk/src"
```
## Usage
```bash
# plum needs adb (brew install android-platform-tools)
adb connect 45.55.191.82:5555 # redroid; skip for a USB phone
cd client
python3 mr_lookup.py --phone "+1 555 123 4567" --client-id 12345 [--dry-run] [--device 45.55.191.82:5555]
python3 -m unittest mr_lookup_test -v # host-free unit tests
```
- `--dry-run` — lookup + vision, but do not POST the record (safe for testing).
- `--json` — emit one JSON result object on stdout (used by the MCP).
### Console (sign-in / calibration)
```bash
2026-06-28 10:55:59 -04:00
client/console-tray/run.sh # menu-bar tray (☎️ icon); Connect → Open Console (http://localhost:8001/ui?app=mr-number — now shows clear ☎️ Mr. Number header in the webui)
2026-06-28 09:06:51 -04:00
```
### MCP (coworker-agent / Claude Desktop)
```bash
cd mcp & & bun run start # stdio server; exposes mr_number_lookup
```
## Layout
```
client/ plum-side lookup + console tray
mr_lookup.py adb drive → screenshot → vision → decide → record
mr_lookup_test.py host-free unit tests (mock adb/vision/network)
console-tray/ macOS menu-bar SSH-tunnel console to the redroid box
mcp/ bun stdio MCP wrapping mr_lookup.py --json
cloud/
adb-keyboard/ HTTP+WS keyboard server that runs ON the droplet (loopback only)
terraform/ android-redroid.tf.reference — read-only copy; canonical IaC is in uvlava
deploy/ install.sh (plum) + deploy-droplet.sh (push adb-keyboard to the box)
docs/archive/ first-attempt (failed) redroid + web-console handoffs, for history
```
## Infrastructure ownership
The redroid droplet itself is **not** provisioned from this repo. Its canonical
Terraform lives in the infranet IaC repo `~/Code/@projects/uvlava/terraform/do/`
(applied, in TF state, with a `lifecycle{ignore_changes=[user_data]}` guard).
`cloud/terraform/android-redroid.tf.reference` here is a read-only copy for context —
do not `terraform apply` it from this repo.