Overzicht
whatsapp-mcp is een server die draait binnen Cloudflare en AI-agents (zoals Claude Code of Claude Desktop) in staat stelt om WhatsApp-chats te lezen en te doorzoeken. De server fungeert als een gekoppeld apparaat, vergelijkbaar met WhatsApp Web, waarbij de telefoon de primaire bron van waarheid blijft.
Belangrijkste functionaliteiten
- Lezen en Zoeken: De AI-agent kan specifieke berichten zoeken, chats samenvatten en lijsten met recente gesprekken opvragen.
- Contactbeheer: De agent kan telefoonnummers koppelen aan namen via externe tools.
- Read-only: De server kan uitsluitend berichten lezen en zoeken; het verzenden van berichten is niet mogelijk.
Technische details
- Architectuur: Maakt gebruik van Cloudflare Workers, Durable Objects en een SQLite-database voor de opslag van berichten en auth-keys.
- Protocol: Gebruikt de opensource bibliotheek
Baileys om te communiceren met WhatsApp.
- Vereisten: Voor een stabiele import van chatgeschiedenis is een Cloudflare Workers Paid plan noodzakelijk vanwege de CPU-limieten.
Risico's en beperkingen
- Servicevoorwaarden: Omdat het geen officieel product is en de WhatsApp-API omzeilt, is het gebruik in strijd met de servicevoorwaarden van WhatsApp.
- Media: Foto's, spraakberichten en documenten worden niet gedownload of getranscribeerd, maar verschijnen als labels (bijv.
[image]).
- Gebruik: De deployment is bedoeld voor één enkele gebruiker per account.
whatsapp-mcp: Laat je AI-agent je WhatsApp-berichten lezen
Je kunt je AI-agent vragen stellen als:
- "Wat zei Dana over de vluchten?"
- "Zoek in al mijn chats naar elk bericht waarin het huurcontract wordt genoemd."
- "Vat samen wat ik deze week heb gemist in de familie-groepsapp."
Hoe het werkt
Je telefoon blijft de "source of truth". De server fungeert als een gekoppeld apparaat waarmee je agent communiceert.
De server houdt geen permanente verbinding met WhatsApp. Wanneer je agent om informatie vraagt, of eenmaal per dag, maakt de server verbinding, verzamelt alle berichten die WhatsApp sindsdien in de wachtrij heeft gezet, schrijft deze naar een eigen database en verbreekt vervolgens de verbinding. Je telefoon blijft normaal functioneren en je blijft meldingen ontvangen.
Je berichten worden opgeslagen in een SQLite-database binnen een Durable Object in je Cloudflare-account. De data wordt nergens anders naartoe gestuurd.
Installatie
Vereisten
- Een Cloudflare-account met het Workers Paid plan (zie de opmerking hieronder).
- Node 20 of later.
- Je telefoon.
Stappenplan
- Clone de repository en installeer de afhankelijkheden:
``bash git clone https://github.com/finereli/whatsapp-mcp cd whatsapp-mcp npm install ``
- Maak een plek voor de sign-in tokens. Kopieer de ID die wordt geprint naar
wrangler.jsonc:
``bash npx wrangler kv namespace create OAUTH_KV ``
- Stel een wachtwoord in voor de pagina waarmee je je telefoon koppelt (minimaal 12 tekens):
``bash npx wrangler secret put OWNER_PASSWORD ``
- Deploy de applicatie:
``bash npm run deploy ``
Wrangler print nu je URL, bijvoorbeeld https://whatsapp-mcp.jouw-naam.workers.dev. Open deze URL. De startpagina bevat de laatste twee stappen:
- WhatsApp koppelen: Scan de QR-code met WhatsApp (Instellingen → Gekoppelde apparaten → Apparaat koppelen). Als je op de telefoon zelf bent en het scherm niet kunt scannen, gebruik dan de optie voor het telefoonnummer. De eerste koppeling importeert je geschiedenis. Je kunt de pagina sluiten zodra de voortgang is voltooid.
- Je agent verbinden: In Claude Code gebruik je het volgende commando:
``bash claude mcp add --transport http whatsapp https://jouw-url/mcp ` Typ vervolgens /mcp en log in met het wachtwoord. Voor andere clients: wijs ze naar dezelfde /mcp` URL.
Opmerking: Als je een eigen domein wilt gebruiken, zie dan de commentaren onderaan wrangler.jsonc.
Opmerking over het Workers Paid plan
Het importeren van een grote geschiedenis vereist het decoderen van veel data in één keer. De standaard CPU-limiet van de gratis Workers-versie is hiervoor te laag. In wrangler.jsonc is deze limiet verhoogd, wat het betaalde plan vereist (enkele dollars per maand). Indien je het gratis plan gebruikt, moet je het limits blok verwijderen, maar houd er rekening mee dat de eerste import dan instabiel kan zijn.
Belangrijke informatie
- Niet officieel: Dit is geen officieel product. WhatsApp biedt geen API voor het lezen van persoonlijke berichten. Deze server gebruikt hetzelfde protocol als WhatsApp Web via de opensource bibliotheek Baileys. Dit is in strijd met de servicevoorwaarden van WhatsApp. Voor een apparaat dat alleen leest is het praktische risico laag, maar niet nul. Gebruik dit alleen op je eigen account en niet om berichten te verzenden.
- Import van geschiedenis: Je krijgt de gegevens die WhatsApp besluit te versturen naar een nieuw gekoppeld apparaat. Dit is mogelijk niet alles. Dit gebeurt slechts één keer per koppeling. Om opnieuw te importeren, moet je opnieuw koppelen (opgeslagen berichten blijven behouden).
- Telefoonnummers versus namen: Sommige chats verschijnen als telefoonnummers omdat WhatsApp niet alle contactnamen doorgeeft aan een gekoppeld apparaat. Je agent kan dit oplossen: de agent kan de naamloze chats oplijsten, de nummers opzoeken in je contacten (via een andere tool, zoals een Google Contacts-connector) en de namen opslaan. De server maakt zelf nooit verbinding met een contactenservice.
- Media: Media worden niet gedownload. Foto's, spraakberichten en documenten verschijnen als labels zoals
[image] of [voice note 12s], inclusief het bijschrift indien aanwezig. Er vindt geen transcriptie plaats.
- Enkele gebruiker: Eén deployment is bedoeld voor één WhatsApp-account en één eigenaar. Dit is bewust zo gedaan omdat elke deployment een volledige geschiedenis en een live login bevat.
- Opnieuw koppelen: Als je telefoon aangeeft dat het apparaat is verwijderd, of als je opnieuw wilt beginnen, vraag dan je agent om
relink uit te voeren, of ga naar /setup en kies "Unlink and scan again".
Functionaliteiten van de AI-agent
| Tool | Functie |
list_chats | Lijst met chats, meest recente eerst. Filteren op naam of nummer mogelijk. |
get_messages | Lees één chat. Pagineren op datum (vooruit/achteruit). |
search_messages | Full-text search over alle chats of binnen één specifieke chat. |
unnamed_chats | Chats die alleen bekend zijn via telefoonnummer, gesorteerd op activiteit. |
setcontactnames | Namen opslaan voor telefoonnummers. Namen blijven gekoppeld aan het nummer. |
sync_now | Direct nieuwe berichten ophalen. |
link_status | Controleert of er een koppeling is, wanneer de laatste pull was en hoeveel data is opgeslagen. |
relink | Koppeling verbreken en opnieuw beginnen (vereist handmatige QR-scan). |
Elke lees-tool controleert eerst of de opgeslagen kopie ouder is dan tien minuten; zo ja, dan wordt deze eerst bijgewerkt via WhatsApp.
Namen toekennen aan chats
Omdat de server geen directe toegang heeft tot je contactenlijst, wordt deze taak overgelaten aan de agent. Je kunt zeggen: "Zoek namen voor mijn naamloze chats". De agent roept dan unnamedchats aan, matcht de nummers met je contacten via zijn eigen tools en slaat de namen op met setcontact_names.
Technische informatie (voor ontwikkelaars en agents)
Architectuur
MCP client → OAuth → Worker (src/index.ts)
/mcp → mcp.ts: Tools, een nieuwe McpServer per verzoek.
/, /setup, /authorize, /login/, /pair/: Landing page, inloggen en pairing UI.
cron 04:00 UTC → pull()
De Worker communiceert via RPC met de WhatsAppStore (een Durable Object genaamd "owner"). De WhatsAppStore bevat:
- SQLite: Auth keys, berichten, chats, contacten, FTS5 index.
- Baileys socket: Alleen geopend tijdens een sessie (pairing of pull).
Bestandsstructuur
src/index.ts: Routes, OAuth-configuratie, inloggen, pairing endpoints en cron.
src/auth.ts: Beheer van de eigenaar (wachtwoord-modus of login-service).
src/phone.ts: Omzetten van telefoonnummers naar WhatsApp JIDs.
src/whatsapp-do.ts: De Durable Object die Baileys-sessies draait.
src/store.ts: Schema, verwerking van Baileys-events naar SQLite en queries.
src/auth-state.ts: Baileys auth state ondersteund door SQLite.
src/mcp.ts: De MCP-tools en instructies voor agents.
src/pages.ts, src/landing.ts, src/privacy.ts, src/tos.ts, src/ui.ts: Alle HTML-onderdelen.
src/ws-shim.ts, src/lru-shim.ts, src/polyfills.ts: Shims om Baileys te laten draaien op workerd.
Datamodel (SQLite)
messages: (chat, id, ts, fromme, sender, pushname, type, body). Media zijn labels in de body.
messages_fts: Een FTS5 index voor full-text search.
chats, contacts, custom_names: Beheer van identiteiten en namen.
alias: Koppeling tussen @lid identifiers en telefoonnummer JIDs.
auth: Baileys credentials en signal keys.
meta: Opslag van metadata, zoals last_pull.
Technische implementatiedetails
Om Baileys te laten werken op Cloudflare Workers (workerd), zijn de volgende shims nodig:
- ws: Gebruikt een wrapper rond de Workers WebSocket met een Upgrade-header voor de Origin-check van WhatsApp.
- whatsapp-rust-bridge: De WASM-module wordt vooraf geëxtraheerd door
vendor-bridge.mjs omdat runtime compilatie verboden is in workerd.
- Timers:
polyfills.ts voegt .unref() toe aan timers.
- lru-cache:
lru-shim.ts schakelt autopurge uit om te voorkomen dat de limiet van 10.000 timers per object wordt overschreden tijdens de eerste synchronisatie.
Configuratie
| Variabele | Type | Doel |
OWNER_PASSWORD | secret | Wachtwoord voor toegang (min. 12 tekens). |
OWNER_EMAIL | var | Toegestane e-mail bij gebruik van login-service modus. |
OPERATOR_NAME | var | Naam van de beheerder op de privacy-pagina. |
DEFAULTCOUNTRYCODE | var | Landcode (cijfers, zonder +) voor nummers zonder prefix. |
LOGIN_ORIGIN | var | Activeert de login-service modus. |
ALLOWED_ORIGINS | var | Toegestane origins voor tokens in login-service modus. |
PIN | secret | Optioneel: activeert /debug routes via de x-pin header. |
OAUTH_KV | binding | Token store voor OAuth en pending sign-ins. |
WA | binding | De Durable Object binding. |
Debugging en Validatie
Bij een ingestelde PIN kunnen de volgende endpoints worden gebruikt (met header x-pin: <PIN>):
/debug: Status van de sessie, koppeling, counts en laatste events.
/debug/pull: Forceert een onmiddellijke pull.
/debug/chats, /debug/messages, /debug/search: Directe toegang tot de store zonder MCP.
/debug/sql?q=: Read-only SELECT queries tegen de database.
/debug/logout: Ontkoppelt het apparaat.
Lokale ontwikkeling: Gebruik npm run dev met een .dev.vars bestand waarin OWNER_PASSWORD is gedefinieerd. Dit draait een lokale Durable Object.
Controleren van wijzigingen:
- Voer
npm run typecheck en npm test uit.
- Deploy en controleer
/debug op paired: true en phase: "idle".
- Test de tools via de agent (listchats, getmessages, search_messages).
Bekende beperkingen
- Namen in WhatsApp die niet zijn opgeslagen, blijven telefoonnummers totdat een agent ze handmatig opslaat.
- Als een dagelijkse pull faalt omdat de sessie is verlopen, krijg je geen actieve melding; dit is pas zichtbaar via
link_status.
- Berichten die bewerkt of verwijderd zijn, worden verwerkt zodra de protocolberichten binnenkomen, maar dit is nog niet uitgebreid getest.
- Het project is getest op één echt account.
Licentie
MIT
whatsapp-mcp: Laat je AI-agent je WhatsApp-berichten lezen
Je kunt je AI-agent vragen stellen als:
- "Wat zei Dana over de vluchten?"
- "Zoek in al mijn chats naar elk bericht waarin het huurcontract wordt genoemd."
- "Vat samen wat ik deze week heb gemist in de familie-groepsapp."
Hoe het werkt
Je telefoon blijft de "source of truth". De server fungeert als een gekoppeld apparaat waarmee je agent communiceert.
De server houdt geen permanente verbinding met WhatsApp. Wanneer je agent om informatie vraagt, of eenmaal per dag, maakt de server verbinding, verzamelt alle berichten die WhatsApp sindsdien in de wachtrij heeft gezet, schrijft deze naar een eigen database en verbreekt vervolgens de verbinding. Je telefoon blijft normaal functioneren en je blijft meldingen ontvangen.
Je berichten worden opgeslagen in een SQLite-database binnen een Durable Object in je Cloudflare-account. De data wordt nergens anders naartoe gestuurd.
Installatie
Vereisten
- Een Cloudflare-account met het Workers Paid plan (zie de opmerking hieronder).
- Node 20 of later.
- Je telefoon.
Stappenplan
- Clone de repository en installeer de afhankelijkheden:
``bash git clone https://github.com/finereli/whatsapp-mcp cd whatsapp-mcp npm install ``
- Maak een plek voor de sign-in tokens. Kopieer de ID die wordt geprint naar
wrangler.jsonc:
``bash npx wrangler kv namespace create OAUTH_KV ``
- Stel een wachtwoord in voor de pagina waarmee je je telefoon koppelt (minimaal 12 tekens):
``bash npx wrangler secret put OWNER_PASSWORD ``
- Deploy de applicatie:
``bash npm run deploy ``
Wrangler print nu je URL, bijvoorbeeld https://whatsapp-mcp.jouw-naam.workers.dev. Open deze URL. De startpagina bevat de laatste twee stappen:
- WhatsApp koppelen: Scan de QR-code met WhatsApp (Instellingen → Gekoppelde apparaten → Apparaat koppelen). Als je op de telefoon zelf bent en het scherm niet kunt scannen, gebruik dan de optie voor het telefoonnummer. De eerste koppeling importeert je geschiedenis. Je kunt de pagina sluiten zodra de voortgang is voltooid.
- Je agent verbinden: In Claude Code gebruik je het volgende commando:
``bash claude mcp add --transport http whatsapp https://jouw-url/mcp ` Typ vervolgens /mcp en log in met het wachtwoord. Voor andere clients: wijs ze naar dezelfde /mcp` URL.
Opmerking: Als je een eigen domein wilt gebruiken, zie dan de commentaren onderaan wrangler.jsonc.
Opmerking over het Workers Paid plan
Het importeren van een grote geschiedenis vereist het decoderen van veel data in één keer. De standaard CPU-limiet van de gratis Workers-versie is hiervoor te laag. In wrangler.jsonc is deze limiet verhoogd, wat het betaalde plan vereist (enkele dollars per maand). Indien je het gratis plan gebruikt, moet je het limits blok verwijderen, maar houd er rekening mee dat de eerste import dan instabiel kan zijn.
Belangrijke informatie
- Niet officieel: Dit is geen officieel product. WhatsApp biedt geen API voor het lezen van persoonlijke berichten. Deze server gebruikt hetzelfde protocol als WhatsApp Web via de opensource bibliotheek Baileys. Dit is in strijd met de servicevoorwaarden van WhatsApp. Voor een apparaat dat alleen leest is het praktische risico laag, maar niet nul. Gebruik dit alleen op je eigen account en niet om berichten te verzenden.
- Import van geschiedenis: Je krijgt de gegevens die WhatsApp besluit te versturen naar een nieuw gekoppeld apparaat. Dit is mogelijk niet alles. Dit gebeurt slechts één keer per koppeling. Om opnieuw te importeren, moet je opnieuw koppelen (opgeslagen berichten blijven behouden).
- Telefoonnummers versus namen: Sommige chats verschijnen als telefoonnummers omdat WhatsApp niet alle contactnamen doorgeeft aan een gekoppeld apparaat. Je agent kan dit oplossen: de agent kan de naamloze chats oplijsten, de nummers opzoeken in je contacten (via een andere tool, zoals een Google Contacts-connector) en de namen opslaan. De server maakt zelf nooit verbinding met een contactenservice.
- Media: Media worden niet gedownload. Foto's, spraakberichten en documenten verschijnen als labels zoals
[image] of [voice note 12s], inclusief het bijschrift indien aanwezig. Er vindt geen transcriptie plaats.
- Enkele gebruiker: Eén deployment is bedoeld voor één WhatsApp-account en één eigenaar. Dit is bewust zo gedaan omdat elke deployment een volledige geschiedenis en een live login bevat.
- Opnieuw koppelen: Als je telefoon aangeeft dat het apparaat is verwijderd, of als je opnieuw wilt beginnen, vraag dan je agent om
relink uit te voeren, of ga naar /setup en kies "Unlink and scan again".
Functionaliteiten van de AI-agent
| Tool | Functie |
list_chats | Lijst met chats, meest recente eerst. Filteren op naam of nummer mogelijk. |
get_messages | Lees één chat. Pagineren op datum (vooruit/achteruit). |
search_messages | Full-text search over alle chats of binnen één specifieke chat. |
unnamed_chats | Chats die alleen bekend zijn via telefoonnummer, gesorteerd op activiteit. |
setcontactnames | Namen opslaan voor telefoonnummers. Namen blijven gekoppeld aan het nummer. |
sync_now | Direct nieuwe berichten ophalen. |
link_status | Controleert of er een koppeling is, wanneer de laatste pull was en hoeveel data is opgeslagen. |
relink | Koppeling verbreken en opnieuw beginnen (vereist handmatige QR-scan). |
Elke lees-tool controleert eerst of de opgeslagen kopie ouder is dan tien minuten; zo ja, dan wordt deze eerst bijgewerkt via WhatsApp.
Namen toekennen aan chats
Omdat de server geen directe toegang heeft tot je contactenlijst, wordt deze taak overgelaten aan de agent. Je kunt zeggen: "Zoek namen voor mijn naamloze chats". De agent roept dan unnamedchats aan, matcht de nummers met je contacten via zijn eigen tools en slaat de namen op met setcontact_names.
Technische informatie (voor ontwikkelaars en agents)
Architectuur
MCP client → OAuth → Worker (src/index.ts)
/mcp → mcp.ts: Tools, een nieuwe McpServer per verzoek.
/, /setup, /authorize, /login/, /pair/: Landing page, inloggen en pairing UI.
cron 04:00 UTC → pull()
De Worker communiceert via RPC met de WhatsAppStore (een Durable Object genaamd "owner"). De WhatsAppStore bevat:
- SQLite: Auth keys, berichten, chats, contacten, FTS5 index.
- Baileys socket: Alleen geopend tijdens een sessie (pairing of pull).
Bestandsstructuur
src/index.ts: Routes, OAuth-configuratie, inloggen, pairing endpoints en cron.
src/auth.ts: Beheer van de eigenaar (wachtwoord-modus of login-service).
src/phone.ts: Omzetten van telefoonnummers naar WhatsApp JIDs.
src/whatsapp-do.ts: De Durable Object die Baileys-sessies draait.
src/store.ts: Schema, verwerking van Baileys-events naar SQLite en queries.
src/auth-state.ts: Baileys auth state ondersteund door SQLite.
src/mcp.ts: De MCP-tools en instructies voor agents.
src/pages.ts, src/landing.ts, src/privacy.ts, src/tos.ts, src/ui.ts: Alle HTML-onderdelen.
src/ws-shim.ts, src/lru-shim.ts, src/polyfills.ts: Shims om Baileys te laten draaien op workerd.
Datamodel (SQLite)
messages: (chat, id, ts, fromme, sender, pushname, type, body). Media zijn labels in de body.
messages_fts: Een FTS5 index voor full-text search.
chats, contacts, custom_names: Beheer van identiteiten en namen.
alias: Koppeling tussen @lid identifiers en telefoonnummer JIDs.
auth: Baileys credentials en signal keys.
meta: Opslag van metadata, zoals last_pull.
Technische implementatiedetails
Om Baileys te laten werken op Cloudflare Workers (workerd), zijn de volgende shims nodig:
- ws: Gebruikt een wrapper rond de Workers WebSocket met een Upgrade-header voor de Origin-check van WhatsApp.
- whatsapp-rust-bridge: De WASM-module wordt vooraf geëxtraheerd door
vendor-bridge.mjs omdat runtime compilatie verboden is in workerd.
- Timers:
polyfills.ts voegt .unref() toe aan timers.
- lru-cache:
lru-shim.ts schakelt autopurge uit om te voorkomen dat de limiet van 10.000 timers per object wordt overschreden tijdens de eerste synchronisatie.
Configuratie
| Variabele | Type | Doel |
OWNER_PASSWORD | secret | Wachtwoord voor toegang (min. 12 tekens). |
OWNER_EMAIL | var | Toegestane e-mail bij gebruik van login-service modus. |
OPERATOR_NAME | var | Naam van de beheerder op de privacy-pagina. |
DEFAULTCOUNTRYCODE | var | Landcode (cijfers, zonder +) voor nummers zonder prefix. |
LOGIN_ORIGIN | var | Activeert de login-service modus. |
ALLOWED_ORIGINS | var | Toegestane origins voor tokens in login-service modus. |
PIN | secret | Optioneel: activeert /debug routes via de x-pin header. |
OAUTH_KV | binding | Token store voor OAuth en pending sign-ins. |
WA | binding | De Durable Object binding. |
Debugging en Validatie
Bij een ingestelde PIN kunnen de volgende endpoints worden gebruikt (met header x-pin: <PIN>):
/debug: Status van de sessie, koppeling, counts en laatste events.
/debug/pull: Forceert een onmiddellijke pull.
/debug/chats, /debug/messages, /debug/search: Directe toegang tot de store zonder MCP.
/debug/sql?q=: Read-only SELECT queries tegen de database.
/debug/logout: Ontkoppelt het apparaat.
Lokale ontwikkeling: Gebruik npm run dev met een .dev.vars bestand waarin OWNER_PASSWORD is gedefinieerd. Dit draait een lokale Durable Object.
Controleren van wijzigingen:
- Voer
npm run typecheck en npm test uit.
- Deploy en controleer
/debug op paired: true en phase: "idle".
- Test de tools via de agent (listchats, getmessages, search_messages).
Bekende beperkingen
- Namen in WhatsApp die niet zijn opgeslagen, blijven telefoonnummers totdat een agent ze handmatig opslaat.
- Als een dagelijkse pull faalt omdat de sessie is verlopen, krijg je geen actieve melding; dit is pas zichtbaar via
link_status.
- Berichten die bewerkt of verwijderd zijn, worden verwerkt zodra de protocolberichten binnenkomen, maar dit is nog niet uitgebreid getest.
- Het project is getest op één echt account.
Licentie
MIT