Skip to content

Releases

v0.7.2

Choose a tag to compare

@Sealjay Sealjay released this 09 Nov 07:48
34c131b

Behaviour change for download_media with output_path: the call now writes a separate copy instead of a hard link to the media cache, so editing an exported file can no longer change the cache. An existing file at output_path is never replaced. If it already holds this message's media the call succeeds without downloading again; otherwise it fails and asks you to choose a new path or remove the file. Exported media now uses its own disk space.

What's Changed

  • fix: isolate download output from the media cache by @jay23606 in #117
  • fix(client): return verified output_path without re-downloading by @Sealjay in #120

Full Changelog: v0.7.1...v0.7.2

v0.7.1

Choose a tag to compare

@Sealjay Sealjay released this 09 Nov 03:34
79be25f

What's Changed

  • docs: position WhatsApp MCP around its current capabilities by @Sealjay in #113
  • perf: speed up multi-arch container publishing by @Sealjay in #114
  • fix: import poll votes from synchronized history by @jay23606 in #115
  • fix(client): tally history poll votes that arrive with their poll by @Sealjay in #116

New Contributors

Full Changelog: v0.7.0...v0.7.1

v0.7.0

Choose a tag to compare

@Sealjay Sealjay released this 08 Nov 07:38
93baa3d

What's Changed

  • docs: consolidate repository guidance by @Sealjay in #88
  • fix(logs): redact chat names, contact names and JIDs in client logs by @benjamin-di in #75
  • fix(client): unwrap history-sync messages before storing them by @benjamin-di in #64
  • fix(events): store captions of incoming image, video and document messages by @benjamin-di in #58
  • fix(send): rate-limit replies and reactions, cache sent replies by @benjamin-di in #79
  • feat(store): include message ID on every list_messages line by @zaeeeeeem in #82
  • Store incoming contact cards as text by @MarioCuautle in #55
  • Cover history-sync group sender recovery by @Sealjay with @Copilot in #89
  • chore: update whatsmeow dependency by @Sealjay with @Copilot in #90
  • Publish release container images to GHCR by @Sealjay with @Copilot in #91
  • feat: enforce read-only WhatsApp tool access by @Sealjay in #93
  • Pin Docker base images and upgrade inherited runtime packages by @Sealjay with @Copilot in #92
  • Add opt-in voice-note transcription via an OpenAI-compatible speech-to-text endpoint by @MarioCuautle in #56
  • fix: require HTTPS for remote transcription services by @Sealjay in #94
  • feat(pairing): opt-in full history sync when linking a device by @benjamin-di in #60
  • feat: expose daemon health and connection readiness by @Sealjay in #96
  • Add read-only WhatsApp Business label support by @MarioCuautle in #53
  • docs: remove retired report badge and link tool count by @benjamin-di in #98
  • docs: refresh guidance and correct project badges by @Sealjay in #99
  • fix(pairing): start a new pairing flow after the previous one expired by @benjamin-di in #77
  • feat(media): recover expired media links by asking the phone to re-upload by @benjamin-di in #73
  • feat(client): apply incoming edits and deletes for everyone to the cache by @benjamin-di in #71
  • Potential fix for code scanning alert no. 1: Workflow does not contain permissions by @Sealjay in #100

New Contributors

Full Changelog: v0.6.0...v0.7.0

v0.6.0

Choose a tag to compare

@Sealjay Sealjay released this 17 Oct 14:23
078ac8c
refactor: single-source serverInfo version, 2026 tools/call e2e, conc…

v0.5.0

Choose a tag to compare

@Sealjay Sealjay released this 22 Sep 05:37

New tools and features

  • Docker support. A multi-stage Dockerfile builds on golang:1.26-bookworm and ships on debian:bookworm-slim with ffmpeg and CA certificates, running as a non-root user and binding to loopback by default. The README covers pairing through a one-off container before serve starts, the -allow-remote + WHATSAPP_MCP_TOKEN override for publishing the port, and re-pairing after WhatsApp's session rotation. (#39, thanks @mikhail-koviazin)

Fixes

  • Native Windows builds work again. The store lock used syscall.Flock, which doesn't exist on Windows. Unix and Windows now have separate implementations, with a LockFileEx-based Windows path and new tests. (#35, thanks @mikhail-koviazin)
  • download_media no longer returns the wrong file. The cache was keyed by filename, so two messages with the same filename could overwrite each other. Entries are now keyed by message ID and checked against the stored size and SHA-256 before use. (#32, thanks @alexbonea)
  • request_sync can walk history backwards. It used a cursor WhatsApp's servers couldn't resolve, so requests silently returned nothing. It now starts from a real cached message (oldest, newest, or nearest a timestamp) and takes new anchor, count and use_lid parameters, including a fallback for history from before the LID migration. (#33, thanks @NellySsenkumba)
  • /pair no longer rate-limits itself. The page refreshes every 5 seconds, and its limiters refilled more slowly than that, so one open page ran out of allowance and got stuck on 429. The limiters now refill faster than the page polls. (#37, thanks @mikhail-koviazin)
  • whatsmeow bumped, with SetStatusMessage adapted to upstream's new SetStatusInput argument. (#29)
  • Claude Desktop config example fixed. claude_desktop_config.json only launches stdio servers, so the README now bridges to the daemon with mcp-remote. (#30, thanks @kbullett)

Breaking changes

  • request_sync now requires chat_jid, and Client.RequestHistorySync takes new anchor, count and use_lid parameters. (#33)

Internal

  • Tests for request_sync argument parsing and a regression test for the /pair rate-limit fix.

Full Changelog: v0.4.1...v0.5.0

v0.4.1

Choose a tag to compare

@Sealjay Sealjay released this 18 Jul 23:55

Fixes

  • Group and blocklist tools now accept +-prefixed phone numbers. add_group_participants, remove_group_participants, create_group, block_contact and unblock_contact parsed recipients through a separate code path that never stripped a leading + or rejected non-digit input, so an E.164 number like +447967960994 silently misrouted. This is the same bug fixed for the send tools in #16, which those paths never picked up.

    Fixed at the root rather than per-tool: the duplicate parser is deleted, so every recipient in the codebase now goes through one NormalizeRecipient. Whitespace trimming moved there too, which the send path gains as a side benefit.

Internal

  • The weekly upstream probe now reports an available whatsmeow bump to a single rolling issue instead of echoing into the Actions run log where nobody reads it. It stays silent when the pin is already current.

v0.4.0

Choose a tag to compare

@Sealjay Sealjay released this 18 Jul 23:44

First release since v0.3.0 (11 May 2026).

New tools and features

  • pairing_status tool — MCP clients can poll a structured setup_state envelope (ready / awaiting_qr with QR payload / error) to drive their own pairing UI, instead of shelling out to the /pair web page.
  • Media resources at whatsapp:// URIs — any MCP client can fetch the decrypted bytes of a media message via the standard resources/read call (whatsapp://media/{chat_jid}/{message_id}), with no size cap — covers videos and large documents that don't fit inline.
  • Inline media in download_media — image and audio messages up to 5 MiB now come back as inline image/audio content alongside the JSON summary, so remote MCP clients can view or hear media without an out-of-band file transfer. Video and documents are unchanged and still resolve to a file path.
  • Send/usync rate limiting — the daemon now throttles outgoing messages (45s floor, 30/hour, stricter for first-contact sends) and is_on_whatsapp lookups (3/minute), to stop a runaway or misbehaving client getting the paired account rate-limited or banned by WhatsApp. Operators can override per-request via an HTTP header for legitimate bursts.
  • Passkey pairing support — picked up from upstream whatsmeow, alongside ongoing WhatsApp protocol updates.

Fixes

  • Contact names now resolve from the synced address book — search_contacts and sender-name display previously only looked at the bare phone number stored per-chat; saved names from your phone's address book were ignored. Both now prefer the real name. (Closes #21, reported by @sidjainn.)
  • Media downloads no longer 403 — a URL-parsing bug was dropping WhatsApp's signed CDN auth parameters, so every media download failed. Downloads now also use WhatsApp's own DirectPath field directly instead of re-deriving it from the URL, making them more robust going forward.
  • No more startup crash-loop on network-mounted stores — pointing -store at an Azure Files SMB share or an ACA EmptyDir mount previously crashed the daemon on a permissions check those mount types don't support. The check is now best-effort on such mounts.

Internal / maintenance

  • Two tech-debt passes across the client, store, daemon, mcp and security packages removed dead code and unused generality (336 lines deleted, 278 added back as shared helpers), with no behaviour change.
  • All 42 MCP tools now explicitly declare their readOnly/destructive/idempotent/openWorld hints.
  • CI no longer double-runs on branch pushes; markdown-only changes skip CI.
  • whatsmeow bumped to 2026-07-18; mcp-go bumped 0.48.0 → 0.56.0; assorted transitive dependency bumps.

Upgrade notes

  • No action required. The one new store column (media DirectPath) is nullable and auto-populated going forward, with existing rows still working via the old fallback — no schema migration step, re-pairing, or deleting store/*.db needed.
  • mcp-go 0.56 adds automatic DNS-rebinding protection: the daemon now rejects requests whose Host header isn't recognised as loopback (403). If your MCP client connects via a hostname behind a proxy rather than 127.0.0.1 directly, point it at 127.0.0.1.
  • Building from source now requires Go 1.25.5+ (was 1.25.0), forced by mcp-go's own module requirements.

v0.3.0

Choose a tag to compare

@Sealjay Sealjay released this 11 May 18:45

Full Changelog: v0.2.1...v0.3.0

v0.2.1

Choose a tag to compare

@Sealjay Sealjay released this 02 May 21:31

Security Hardening

  • Fix downloaded media file permissions from 0644 to 0600
  • Cap list_messages limit to 100, context_before/context_after to 20
  • Sanitise ffmpeg stderr to strip file paths before returning to MCP callers
  • Add CSRF token validation on /pair/reset (single-use tokens)
  • Resolve "localhost" via DNS in isLoopbackAddr instead of trusting the string literal

Full Changelog: v0.2.0...v0.2.1

v0.2.0

Choose a tag to compare

@Sealjay Sealjay released this 02 May 17:14

Full Changelog: v0.1.0...v0.2.0