neonize-whatsapp-gateway
by seasayDev
README.md
# neonize-whatsapp-gateway
A small, reusable **WhatsApp capture + messaging layer** built on top of
[`neonize`](https://github.com/krypton-byte/neonize) (Python wrapper around
[`whatsmeow`](https://github.com/tulir/whatsmeow)).
Out of the box, `neonize`/`whatsmeow` does **not** give you an inbox: it
delivers messages using `@lid` (Linked-Device) JIDs and does not populate a
contacts table. This project fixes that with a thin capture + SQLite layer
and a set of MCP-compatible tools, so an LLM agent (Hermes, Claude, etc.)
can **read your messages, list chats, manage contacts, and reply**.
## Features
- π₯ **Inbox capture** β every incoming/outgoing message is stored in a local
SQLite DB (`inbox.db`), with `from_me`, `media_type`, `pushname`, timestamp.
- βοΈ **Readable contacts** β LID JIDs are auto-resolved to real phone numbers
via `get_pn_from_lid`, so your contact book is human-readable.
- π¬ **MCP-compatible stdio server** (`neonize_gateway.py`) exposing tools:
`whatsapp_send`, `whatsapp_send_image`, `whatsapp_send_file`,
`whatsapp_get_messages`, `whatsapp_list_chats`, `whatsapp_get_contacts`,
`whatsapp_add_contact`, `whatsapp_reply`.
- ποΈ **Voice notes transcription** β `voice_handler.py` downloads incoming
voice messages, decodes OGG/Opus β WAV with ffmpeg, and transcribes them
with [faster-whisper](https://github.com/SYSTRAN/faster-whisper). The
transcript is stored in the inbox (and optionally auto-replied as text).
- π§ **Fully configurable** via environment variables β no hardcoded paths.
## Why this exists
> "Can you read my WhatsApp inbox? Why don't I have access to my contacts?
> Can you make the system read messages and reply to conversations?"
The stock library answers "no" to all three. This repo turns that into "yes".
## Install
```bash
pip install neonize # ships prebuilt wheels with the Go backend
# or from this repo:
pip install -r requirements.txt
```
> **Platform note:** the Go backend needs **glibc**. On Android/Termux run
> everything inside `proot-distro login ubuntu`.
## Pair your account (first time only)
```bash
python pairing.py
```
It prints an 8-character code. In WhatsApp go to
**Linked Devices β Link a device β Link with phone number** and enter it.
The session is saved in the DB and you never pair again.
## Run
Capture only:
```bash
python capture_daemon.py
```
As an MCP server (stdio) β e.g. plug it into an LLM gateway:
```bash
python neonize_gateway.py
```
### Environment variables
| Variable | Default | Meaning |
|-----------------|--------------|----------------------------------|
| `NEONIZE_DB` | `./bot.db` | whatsmeow session DB |
| `DB_PATH` | (alias) | same as `NEONIZE_DB` |
| `INBOX_DB` | `./inbox.db` | capture SQLite DB |
Example:
```bash
NEONIZE_DB=/secure/bot.db INBOX_DB=/secure/inbox.db python capture_daemon.py
```
## MCP tools
| Tool | Description |
|------|-------------|
| `whatsapp_send` | Send a text message (phone or JID) |
| `whatsapp_send_image` | Send an image (local path or URL) |
| `whatsapp_send_file` | Send a document (local path or URL) |
| `whatsapp_get_messages` | Read last N captured messages (filter by chat/direction) |
| `whatsapp_list_chats` | List unique conversations |
| `whatsapp_get_contacts` | Read the contact book (local carnet + whatsmeow fallback) |
| `whatsapp_add_contact` | Manually register a contact (name β JID) |
| `whatsapp_reply` | Send a message into an existing conversation |
The MCP server speaks JSON-RPC 2.0 over stdio, so any MCP-compatible client
can call these tools directly.
## Reading the inbox directly (no MCP needed)
```python
import sqlite3
c = sqlite3.connect("inbox.db")
for r in c.execute(
"SELECT chat, from_me, text, media_type, timestamp "
"FROM messages ORDER BY id DESC LIMIT 10"
):
print(r)
```
## Voice notes (transcription)
`voice_handler.py` turns incoming WhatsApp voice messages into text:
```bash
# dependencies (mobile/CPU-friendly β no torch/CUDA)
pip install faster-whisper
# ffmpeg must be on PATH (or set FFMPEG_BIN to its absolute path)
apt-get install ffmpeg # Debian/Ubuntu
# on Termux/Android ffmpeg lives at /data/data/com.termux/files/usr/bin/ffmpeg
python voice_handler.py # capture + log transcripts
AUTO_REPLY=1 python voice_handler.py # also send the transcript back as a text reply
```
How it works: on a `MessageEv` with `audioMessage`, it calls
`download_media_with_path`, decodes the OGG/Opus blob to 16 kHz mono WAV with
ffmpeg, then runs `faster_whisper.WhisperModel("base","cpu")` and stores the
transcript in the inbox (`media_type = "voice"`, `text = "[voice] <transcript>"`).
The first run downloads the whisper model from HuggingFace (~140 MB for `base`).
> **Performance note:** use `faster-whisper` (CTranslate2, int8) rather than
> `openai-whisper` on phones β it avoids the ~800 MB torch/CUDA pull and is
> 5β10Γ faster on ARM CPUs.
## Important caveats
- **One client per DB.** Only ONE neonize client may connect to the session
DB at a time. Do **not** run `capture_daemon.py` and `neonize_gateway.py`
against the same `NEONIZE_DB` simultaneously β the session will thrash.
- **`whatsmeow_contacts` is empty by default.** neonize does not force the
WhatsApp contact app-state sync. This project builds its own contact book
from captured messages + LIDβPN resolution.
- **`MessageEv` only fires for received messages.** Sending via
`send_message` does not echo an event to the same client. To verify
capture, message yourself or have a contact reply.
- **ToS.** Automating WhatsApp may violate WhatsApp/Meta Terms of Service.
Use for personal/experimental purposes at your own risk.
## License
MIT β use freely, but respect WhatsApp's terms.
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues