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

  1. Clone de repository en installeer de afhankelijkheden:

``bash git clone https://github.com/finereli/whatsapp-mcp cd whatsapp-mcp npm install ``

  1. 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 ``

  1. Stel een wachtwoord in voor de pagina waarmee je je telefoon koppelt (minimaal 12 tekens):

``bash npx wrangler secret put OWNER_PASSWORD ``

  1. 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

ToolFunctie
list_chatsLijst met chats, meest recente eerst. Filteren op naam of nummer mogelijk.
get_messagesLees één chat. Pagineren op datum (vooruit/achteruit).
search_messagesFull-text search over alle chats of binnen één specifieke chat.
unnamed_chatsChats die alleen bekend zijn via telefoonnummer, gesorteerd op activiteit.
setcontactnamesNamen opslaan voor telefoonnummers. Namen blijven gekoppeld aan het nummer.
sync_nowDirect nieuwe berichten ophalen.
link_statusControleert of er een koppeling is, wanneer de laatste pull was en hoeveel data is opgeslagen.
relinkKoppeling 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:

  1. ws: Gebruikt een wrapper rond de Workers WebSocket met een Upgrade-header voor de Origin-check van WhatsApp.
  2. whatsapp-rust-bridge: De WASM-module wordt vooraf geëxtraheerd door vendor-bridge.mjs omdat runtime compilatie verboden is in workerd.
  3. Timers: polyfills.ts voegt .unref() toe aan timers.
  4. 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

VariabeleTypeDoel
OWNER_PASSWORDsecretWachtwoord voor toegang (min. 12 tekens).
OWNER_EMAILvarToegestane e-mail bij gebruik van login-service modus.
OPERATOR_NAMEvarNaam van de beheerder op de privacy-pagina.
DEFAULTCOUNTRYCODEvarLandcode (cijfers, zonder +) voor nummers zonder prefix.
LOGIN_ORIGINvarActiveert de login-service modus.
ALLOWED_ORIGINSvarToegestane origins voor tokens in login-service modus.
PINsecretOptioneel: activeert /debug routes via de x-pin header.
OAUTH_KVbindingToken store voor OAuth en pending sign-ins.
WAbindingDe 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:

  1. Voer npm run typecheck en npm test uit.
  2. Deploy en controleer /debug op paired: true en phase: "idle".
  3. 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