Repository navigation
Releases: BrOrlandi/whatsapp-mcp
Release list
v1.3.0-beta.2
Fixes the WhatsApp connection dropping about every 50 minutes, and the
ingestion that stopped a few days later because of it. The tools and the panel
are those of 1.3.0-beta.1.
Fixed
- The connection no longer drops every 50 minutes. The official Evolution
Go 0.7.2 loses the acknowledgement of a media Status when it reconnects, and
WhatsApp then ends the connection about every 50 minutes (Unknown stream error: <stream:error><ack class="status" … type="media"/>in Evolution's log),
delivering the same Status again each time. Messages arrived late but were not
lost. - Ingestion no longer stops after a few days. Every one of those reconnects
left a Postgres connection pool open in Evolution, and after about a hundred
of them its Postgres refused new connections: Evolution could no longer load
the session, and nothing new was indexed. - The session comes back on its own after a restart. Evolution now
reconnects the paired number when its container starts
(CONNECT_ON_STARTUP), instead of leaving WhatsApp disconnected until
someone reconnected it from the panel.
The first two are bugs in Evolution Go 0.7.2
(evolution-go#211,
#185).
Their fix, evolution-go#190,
has not been released, so the stack now runs an unofficial build of 0.7.2 with
it applied: ghcr.io/brorlandi/whatsapp-mcp:evolution-0.7.2-patch.1, built by
this repository (see deploy/evolution). The
stack goes back to the official image once Evolution publishes the fix
(#6).
Updating
update.sh and the panel's Atualizar button bring the new compose file and the
new Evolution image. Evolution's container is recreated, which reconnects
WhatsApp once; the pairing is kept, so no QR code is needed.
- If you copied the compose file, take the new one. It changes the
evolution-goimage and addsCONNECT_ON_STARTUP: "true". - If Evolution's Postgres already ran out of connections (
pq: sorry, too many clients alreadyin Evolution's log), recreating Evolution's container
releases them. EVOLUTION_IMAGEselects another Evolution image; leave it unset.
v1.3.0-beta.1
The server version catches up with WhatsApp MCP Local 1.3.0: the same 40 MCP
tools as Local (plus send_contact and set_transcription_key), webhooks, and the
same control panel.
The version number jumps from 0.4 to 1.3 to match WhatsApp MCP Local: from
here on, the same version on both means the same tools and the same panel.
The -beta stays until this release has been run against a real WhatsApp
session; the schema can still change before 1.3.0.
New tools
- Reply, mention and draft.
send_text_messagequotes an earlier message
(reply_to), mentions people in a group (mentions, written in the text as
@Number) and, withdry_run, returns the draft and its recipient without
sending.send_media_messagegainsreply_to,dry_runand stickers. - Forward, mark as read, "typing…".
forward_messageresends a message
marked as forwarded, media included;mark_chat_readclears a chat on the
phone and sends the blue ticks;send_typingshows "typing…" or
"recording audio…". - Who is waiting for an answer.
list_unansweredlists the chats whose
latest message is from the other side, ignoring a closing "ok" or "obrigado",
optionally with the groups that mentioned the account;list_unreadlists
what the phone shows as unread;list_mentionsthe messages that mention the
account.mark_handledandsnooze_chattake a chat off those lists until
someone writes again — kept in the gateway, invisible to the other side. - Counting and exporting.
message_statscounts by chat, sender, day or
month;get_message_contextreads around one message;export_messages
writes NDJSON and hands it over through a temporary link;
get_chat_messagesandsearch_messagestakefields,
max_content_charsand (reading)count_only. - Groups.
manage_group_participants,update_group,
get_group_invite_linkandleave_group. Removing someone, resetting the
link and leaving ask for confirmation. health: one verdict and the checks behind it.- Kept files.
download_mediakeeps a copy of each file on the server's
new data volume — it stays readable after WhatsApp discards it — and returns
it as an image, an audio or a file block; files over 20 MiB come as a link.
media_statsandpurge_mediameasure and clear the volume. transcribe_audiogives Whisper the conversation as context and returns it
with a review instruction;save_transcriptkeeps a correction's original
asraw_text. Every message tool takes an optionalchat_jid.- Every tool carries MCP annotations (
readOnlyHint,destructiveHint), and
the server's instructions tell the assistant about webhooks.
Webhooks
- Configurações › Webhooks in the panel: a script receives every new
message, reaction or read receipt as it arrives, signed with HMAC-SHA256.
Add, test, turn off and delete each one, and see its last delivery; a
webhook that stops answering is turned off by itself. A documentation page
shows each delivery's JSON. The deliveries are the same as Local's, plus
instance_id. See docs/webhooks.md.
The panel
- The panel now looks and works like Local's: Configurações behind the
gear (MCP address, account, webhooks, transcription, updates, appearance,
downloaded files, data), tabs Conectar MCP, WhatsApp, Status,
Funções, Receitas and Ajuda, a step-by-step page per AI tool
(Claude Desktop, Claude Code, ChatGPT / Codex, Cursor, another one) that
finishes by itself when the tool connects, connections shown with each
tool's logo, light, dark or system theme, and a Help tab with the common
questions and examples. The old addresses redirect.
Ingestion
- The index reads quotes, mentions, forwards, reactions, polls and media file
names, and applies edits and deletions to the message they change. Rows
indexed before are filled in from their stored events on the first start. - The gateway consumes
READ_RECEIPT(the newreceiptqueue), which is how
reading a chat on the phone clears it inlist_unread.
Updating to this version
update.shbrings the newdocker-compose.yml: Evolution restarts with
READ_RECEIPTinAMQP_GLOBAL_EVENTS, and the gateway gets the
whatsapp_mcp_datavolume (MEDIA_DIR,EXPORT_DIR) andINTERNAL_URL.
Migrations014to017add the webhooks, settings, triage marks, chat
state, message details and the transcript's raw text.- Unread counts start from the moment of the update for chats the gateway has
no read information about; a history sync or reading the chat on the phone
fills it in.
Fixes
- Media WhatsApp has already discarded — its servers keep a file only for a
while after it is sent — is now reported as that.download_mediasays the
media expired and that only the sender resending it brings it back;
link: truefetches the file before handing out a URL, so it fails there
with the reason instead of giving a URL that answers a bare 502, and keeps
the file for the link so the download is immediate. A large file that was
not kept and has expired by the time it is fetched answers 410. - The index's gap warnings sent the client to
backfill_gap, a tool that
does not exist. They now namesync_historywithbefore.
Full Changelog: v0.4.0-beta.1...v1.3.0-beta.1
v0.4.0-beta.1
The panel can update the server it runs on, voice notes can be transcribed on
the user's own machine, and the stack fits a 1 GB server.
Updating from the panel
- The update notice now has an Atualizar button. It runs the same
update.shan operator would run by SSH — database dump first — and the
panel follows its progress until the new version answers. The gateway never
touches Docker: the button leaves a request in a directory shared with the
host, and a systemd unit installed byinstall.sh(and by the next
update.sh) carries it out. It accepts only a version GitHub has published. - A Dokploy deployment can use the same agent in
dokploymode, which moves
WHATSAPP_MCP_TAGthrough Dokploy's API and redeploys. - The gateway remembers the newest version that ever ran against its
database. Starting an older one — a redeployed stale pin, an update undone —
raises a warning on every panel page, since migrations do not run backwards,
with a button back to that version when the agent is there. - The gateway container now runs as uid 10001, so the host can give it the
shared directory. Migration013_deployed_version.sqladds one table.
Local transcription
- The tool descriptions now tell a client that can run commands on the
user's machine to transcribe locally first —mlx-whisperon Apple
Silicon,faster-whisperorwhisper.cppon an NVIDIA GPU — and to use
transcribe_audio(OpenAI) only when that is not possible. Local is free and
the audio never leaves the machine. download_mediatakeslink: trueand answers with a temporary URL and a
curlcommand instead of the base64 file, so a voice note does not have to
pass through the conversation. The link needs no credential, is bound to one
message and expires after ten minutes.save_transcriptstores a transcript made elsewhere.get_chat_messages
andsearch_messagesnow return every kept transcript in the message's
transcriptfield, and search matches words spoken in voice notes.
Smaller machines, and AWS
- The stack runs on 1 GB of RAM. On a machine with less than 2 GB and no swap,
the installer adds a 2 GB swap file, which is what gets a 1 GB plan through
the image pulls and the first history sync. A 1 GB AWS Lightsail instance ran
the whole stack at about 520 MB used, with nothing killed. - docs/aws.md and docs/aws.pt-BR.md walk
through Lightsail: the US$ 7 plan, why the price is the same in every
region, pinning a static IP before installing, opening 443, the
builder.aws.com projects whose region is fixed, and the AWS CLI commands an
agent such as Claude Code can run while the user only signs in. The
README's install prompt offers that route.
Fixes
- A fresh install failed at "starting the stack":
quay.io/minio/minio
started answering 401, after MinIO archived its community edition and
stopped serving it anywhere. MinIO is gone from the stack instead of being
pulled from somewhere else — it never held anything. Evolution only writes
media to it withWEBHOOK_FILESon, which this stack leaves off, and no
bucket was ever created; the gateway fetches media from WhatsApp through
/message/downloadmedia. An existing instance loses the idle container on
its next update, and the emptywhatsapp-mcp_minio_datavolume can be
removed withdocker volume rm whatsapp-mcp_minio_data. TheMINIO_*
lines left in its.envare ignored. - Voice notes that arrived through a history sync could not be downloaded or
transcribed ("the stored payload carries no media"). The media lookup only
understood live events; a history sync stores whole conversations, and the
message is now found among them by its id. - A conversation WhatsApp moved to a LID (
…@lid) was split in two: the
history under the phone number, the newest messages under the LID. The
gateway now records which LID belongs to which number — from the
RecipientAlt/SenderAltof live messages and thepnJIDof history syncs
— andlist_chatsshows one conversation,get_chat_messagesreads both
JIDs whichever one is asked for. Messages keep the JID WhatsApp used, so
deleting, editing and reacting still address them correctly. Migration
012_jid_aliases.sqlpairs what is already indexed; LID chats whose number
WhatsApp never revealed stay on their own.
v0.3.0-beta.2
Fixes
transcribe_audiofailed on every voice note with "Evolution returned no
audio". Evolution Go returns the media as a data URI
(data:audio/ogg; codecs=opus;base64,…) with an emptymimetype, and the
tool was decoding it as bare base64. It now reads the format from the URI and
falls back to Ogg/Opus, which is what WhatsApp voice notes are.
v0.3.0-beta.1
Voice notes can now be read. An instance that saves an OpenAI key gets its
WhatsApp audio transcribed on request.
Voice-note transcription
transcribe_audioturns a WhatsApp voice note into text with OpenAI's
Whisper. An AI client cannot hear the audiodownload_mediareturns, so the
gateway does this one piece of model work itself — only with an OpenAI key the
operator saves, and billed to that key.- The key is saved from the panel's new Transcrição page or with the
set_transcription_keytool. Both check it with OpenAI before saving, and
neither shows it again: only its last four characters. - The Transcrição page walks someone who has never used the OpenAI
platform through getting a key — account, credit, key — with a button to
each OpenAI page and what it will cost. Once a key is saved, it links to
OpenAI's usage, credit, spending-limit and key pages instead. - When there is no key, or OpenAI refuses it,
transcribe_audioanswers with
the same steps and links, so the AI client can guide the user through setup
instead of reporting an error. - Every transcript is kept, so asking again for the same voice note costs
nothing.whatsapp_statusreports whether transcription is configured. - The update adds two tables (migration
011_transcription.sql); nothing
existing changes. The gateway needs outbound HTTPS toapi.openai.comfor
transcription to work.
Publishing
- The
latestimage tag and the GitHub release marked Latest now follow the
newest version, beta included. Pinning nothing used to leave an instance on
0.1.0 — dozens of commits old, under the previous licence — while the beta
was the version to run.
v0.2.0-beta.1
Full Changelog: v0.1.0...v0.2.0-beta.1
Full Changelog: v0.1.0...v0.2.0-beta.1
v0.1.0
Full Changelog: https://github.com/BrOrlandi/whatsapp-mcp/commits/v0.1.0
Full Changelog: https://github.com/BrOrlandi/whatsapp-mcp/commits/v0.1.0
Full Changelog: https://github.com/BrOrlandi/whatsapp-mcp/commits/v0.1.0