wa
Provides a safety-first interface for WhatsApp automation, including sending messages and media, scheduling, searching messages, managing chats, resolving contacts, transcribing voice notes, and monitoring daemon status, all through a non-bypassable safety pipeline with allowlist, rate limiting, and draft approval.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@wasend 'Meeting at 5' to 5511999999999"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
wa
Personal WhatsApp automation CLI + daemon, written in Go.
A hexagonal Go daemon that owns a WhatsApp Multi-Device session and a thin JSON-RPC client that talks to it — safe enough to let a language model send messages on your behalf, crash-safe enough to survive a power loss mid-migration, and paranoid enough to refuse every destructive flag you might expect.
Quickstart · Install · Manual · Architecture · Security · Contributing · Português (BR)
Capability
Pattern. Persistent WhatsApp daemon over a Unix socket — one wad process holds the Multi-Device session, ratchet store, and websocket; a thin wa JSON-RPC client invokes it.
Trade-off. ~30 MB RSS per profile and a 5–8 s cold connect, in exchange for sub-second warm-call latency on every subsequent wa send. Per-call session reattachment is avoided entirely.
Use when. A shell pipeline, cron job, or Claude Code plugin needs to dispatch WhatsApp messages with predictable latency and a non-overridable safety pipeline (default-deny allowlist + rate limiter + warmup ramp + append-only audit log) sitting below every RPC path.
brew install yolo-labz/tap/wa
wad & # daemon, single instance per profile
wa pair # QR-code pairing on first run
wa allow add 5511999999999@s.whatsapp.net --actions send
wa send --to 5511999999999@s.whatsapp.net --body "hello"Related MCP server: MCP WPPConnect Server
Demo
A non-interactive 15-second asciinema cast covering wa --help, wa daemon status, two wa send calls (warm-call latency under 500 ms), and wa allow list is checked into the repo at docs/assets/wa-demo.cast. Replay locally:
asciinema play docs/assets/wa-demo.castA hosted player embed will land in a follow-up PR after the cast is uploaded to asciinema.org.
How wa compares
Closest peers in the reverse-engineered-WhatsApp ecosystem:
Capability |
|
| |
Persistent daemon (sub-second warm-call) | yes | no (per-call session attach) | no (browser-driven) |
JSON-RPC over Unix socket | yes | n/a (library, not a daemon) | no (Chrome bridge) |
Default-deny allowlist (per-action) | yes | manual implementation | no |
Non-overridable rate limiter (2/30/1000) | yes | manual implementation | no |
Warmup ramp for fresh sessions | yes | manual implementation | no |
Append-only JSON-Lines audit log | yes | manual implementation | no |
SLSA L2 + Sigstore signed releases | yes | n/a | no |
Dual SBOM (CycloneDX 1.6 + SPDX 2.3) | yes | n/a | no |
| yes | depends on consumer | no (browser-driven) |
Inbound prompt-injection firewall | yes | n/a | no |
For multi-tenant REST gateways see EvolutionAPI or WAHA — different shape of problem, listed in What this is NOT.
What this is
Two binaries, one repo:
wad— long-running daemon that owns the WhatsApp session, the SQLite ratchet store, and the websocket toweb.whatsapp.com. Runs undersystemd(Linux),launchd(macOS), or a NixOS module. Single-instance per profile, never as root.wa— thin JSON-RPC client that speaks towadover a unix socket. This is what shell scripts, cron jobs, and Claude Code plugins actually invoke.
It is built on go.mau.fi/whatsmeow — the library that powers mautrix-whatsapp at production scale — because it is the only reverse-engineered WhatsApp library actively maintained in 2026. It also ships a safety-first MCP server (wa mcp serve) so an AI agent drives WhatsApp through the same non-bypassable safety pipeline — draft-gated by default. See MCP server.
What this is NOT
Not a bulk-messaging tool. The rate limiter is non-overridable and there is no
--forceflag anywhere.Not a multi-tenant SaaS. Each
wainstall is scoped to one person, with optional multi-profile isolation for work/personal splits.Not a Matrix bridge. Use
mautrix-whatsappif that's what you want.Not a REST gateway. Use
EvolutionAPIorWAHAif that's what you want.Not the official WhatsApp Cloud API. This project uses the reverse-engineered Multi-Device protocol via
whatsmeow.
Quickstart
# Install (Homebrew — macOS + Linuxbrew)
brew install yolo-labz/tap/wa
# Or via Nix (recommended for NixOS/nix-darwin users)
nix profile install github:yolo-labz/wa
# Or the checksum-verified installer (80 lines — inspect first if you like)
curl -fsSL https://raw.githubusercontent.com/yolo-labz/wa/main/install.sh | bash
# Or Docker — single distroless container (~12 MB); /data holds the session
docker compose up -d # see docker-compose.yaml; pair via `docker compose exec`
# Start the daemon (default profile)
wad &
# Pair your phone — QR code in terminal
wa pair
# Allowlist yourself (default-deny policy)
wa allow add 5511999999999@s.whatsapp.net --actions send
# Send a message
wa send --to 5511999999999@s.whatsapp.net --body "hello from wa"
# Install as a persistent system service
wad install-service --profile default
# Hand it to an AI agent — MCP over stdio, draft-gated sends by default:
# the agent PROPOSES messages into a human-review queue; nothing leaves
# until you run `wa draft approve`. Add to Claude Desktop/Code, Cursor:
# {"mcpServers": {"wa": {"command": "wa", "args": ["mcp", "serve"]}}}
wa mcp serve --helpThe recipient flag is spelled --to, --jid, or --group depending on the command; --chat <jid> is accepted as a universal alias on all of them (the original flags still work).
For the full tour including multi-profile setup, shell completion, migration, and the audit log, see docs/manual.md.
MCP server
wa mcp serve exposes the daemon to AI agents over the Model Context Protocol (stdio transport). Every tool call runs through the same non-bypassable safety pipeline as the CLI — default-deny allowlist, enforced rate limits (2/min · 30/hour · 1000/day with warmup), and an append-only audit log. Sends default to draft mode: the model proposes a message into a human-review queue and nothing leaves until you run wa draft approve. That draft-gate is the point — it is what makes handing WhatsApp to an autonomous agent safe.
Live on the official MCP Registry as io.github.yolo-labz/wa; one-click install via the signed .mcpb bundle on each release, or wire it manually into Claude Desktop/Code or Cursor:
{ "mcpServers": { "wa": { "command": "wa", "args": ["mcp", "serve"] } } }Tools (12):
Tool | Purpose |
| Send (or draft) a message through the safety pipeline |
| Send (or draft) a media file |
| Schedule a send for later (drafts respected) |
| List pending drafts awaiting human approval |
| Full-text search across synced messages |
| Fetch recent messages of one chat |
| List chats with recent activity |
| Resolve a name/phone to a JID |
| Group metadata and participants |
| Block until a matching inbound event arrives |
| Transcribe a voice note |
| Daemon connection and session status |
It also serves resources (read-only context surfaces) and prompts (pre-built workflows) per the MCP spec. Scope the surface with --toolsets; the send mode is draft (default), direct, or deny, and a read-only set hides every mutating tool.
See docs/mcp-registry.md for the registry publish flow and bundle internals.
Install
Homebrew (macOS + Linux)
brew install yolo-labz/tap/waNix flake
# One-shot
nix run github:yolo-labz/wa -- profile list
# Install to profile
nix profile install github:yolo-labz/wa
# Dev shell (go + gopls + golangci-lint + goreleaser + sqlite + jq)
nix develop github:yolo-labz/waNixOS module — import the system module and enable:
{
inputs.wa.url = "github:yolo-labz/wa";
outputs = { self, nixpkgs, wa, ... }: {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
modules = [
wa.nixosModules.default
{ services.wa.enable = true; services.wa.profile = "default"; }
];
};
};
}home-manager module — import for a per-user installation:
{
imports = [ wa.homeManagerModules.default ];
services.wa = {
enable = true;
profile = "default";
autoStart = true;
};
}GoReleaser tarball + supply-chain verification
VERSION=v2.0.5 # pin to a known tag
ARCH=linux_amd64 # or darwin_arm64 / linux_arm64
BASE="https://github.com/yolo-labz/wa/releases/download/$VERSION"
# 1. Download the tarball + checksums
curl -LO "$BASE/wa_${VERSION#v}_${ARCH}.tar.gz"
curl -LO "$BASE/checksums.txt"
# 2. Verify the SHA256 (defends against accidental corruption)
sha256sum -c checksums.txt --ignore-missing
# 3. Verify the SLSA-L2 attestation against THIS tarball (not just the
# manifest) via GitHub's native attestation store. From v2.0.5 onward
# every artifact (.tar.gz / .deb / .rpm / .apk) is registered as its
# own attestation subject — earlier releases (≤ v2.0.4) only attested
# `checksums.txt` and would 404 on per-artifact verify. Requires
# `gh` CLI ≥ 2.50 (Sigstore bundle v0.3.1 support). The verify step
# transparently checks Rekor v2 transparency-log inclusion proof on
# the Sigstore bundle — no separate `rekor-cli` invocation needed.
gh attestation verify "wa_${VERSION#v}_${ARCH}.tar.gz" --repo yolo-labz/wa
# 4. Install
tar xzf "wa_${VERSION#v}_${ARCH}.tar.gz"
install -m 0755 wa wad ~/.local/bin/The gh attestation verify step proves that this exact tarball was produced by the yolo-labz/wa GoReleaser job on the exact commit SHA the tag points at. Every release ships:
wa_<version>_<os>_<arch>.tar.gz— the platform tarballchecksums.txt— SHA256 of every artifactchecksums.txt.sigstore.json— Cosign-signed Sigstore bundle forchecksums.txt(legacy/optional verify path; not needed when usinggh attestation verifyagainst the artifact above)sbom.cdx.json— CycloneDX 1.6 SBOM (full repo, syft)sbom.spdx.json— SPDX 2.3 SBOM (full repo, syft)sbom.gomod.{wa,wad}.cdx.json— Go-native CycloneDX SBOMs (cyclonedx-gomod, per binary, with stdlib + license info)openvex.json— OpenVEX 0.2 statement file. VEX-aware scanners (Trivy, Grype) consume this to filter "is this CVE actually exploitable inwa?" — most transitive CVEs arenot_affectedbecause thedepguard-enforced port boundary keeps them off the runtime path. Statements grow as findings emerge; current baseline is empty pending per-CVE triage.CHANGELOG.md— git-cliff generated changelog
darwin users — unsigned release: releases cut without an Apple Developer account ship the darwin-arm64 binary unsigned and un-notarized. Gatekeeper will quarantine it on first launch. Strip the quarantine flag before running:
xattr -cr ~/.local/bin/wa ~/.local/bin/wadOr install via the Homebrew tap (
brew install yolo-labz/tap/wa) — brew rebuilds from source locally and bypasses the quarantine entirely. Signed + notarized darwin binaries return on the next GA tag cut afterAPPLE_DEVELOPER_ID_APPLICATION_{CERT,KEY}secrets are populated.
go install
The module path includes the /v2 suffix per Go's semantic import versioning rule for v2+ releases.
# Pin to a tag (recommended — reproducible builds need a known revision):
go install github.com/yolo-labz/wa/v2/cmd/wa@v2.0.13
go install github.com/yolo-labz/wa/v2/cmd/wad@v2.0.13
# Or follow main:
go install github.com/yolo-labz/wa/v2/cmd/wa@latest
go install github.com/yolo-labz/wa/v2/cmd/wad@latestgo install on a tag does NOT inherit the GoReleaser build flags (-trimpath, -buildvcs=true, ldflag-stamped version). The resulting binary will run, but wa --version reports (devel). Use the GoReleaser tarball or the Homebrew tap if version-stamped, reproducible binaries matter to you.
Multi-profile
Run two WhatsApp accounts side-by-side — personal and work, or one per client — with full process isolation. Each profile has its own session.db, allowlist.toml, audit.log, rate limiter, unix socket, and warmup timestamp.
wa profile create work
wad --profile work &
wa --profile work pair
wa --profile work status
wa profile list
# PROFILE ACTIVE STATUS JID LAST_SEEN
# default * connected 5511999999999@s.whatsapp.net 2026-04-11T17:00:00Z
# work connected 5511888888888@s.whatsapp.net 2026-04-11T17:00:00ZProfile selection precedence (highest wins):
--profile <name>flagWA_PROFILEenv var (empty = unset)$XDG_CONFIG_HOME/wa/active-profilepointerSingleton (if exactly one profile exists)
Literal
default
See docs/manual.md §4.
Safety
wa is safe enough to let a language model invoke it on your behalf. The safety pipeline is non-overridable and lives inside the daemon, below every RPC path:
Allowlist, default-deny. Per-action (
read/send/group.add/group.create). Hot-reloaded on SIGHUP. Mutated viawa allow add/remove.Rate limiter. 2/sec, 30/min, 1000/day per profile. No
--forceflag. Ever.Warmup ramp. Fresh sessions run at 25 % caps for days 0–7, 50 % for days 8–14, 100 % after. Timestamp sourced from the session store so daemon restarts don't reset the clock.
Audit log. Append-only JSON Lines at
$XDG_STATE_HOME/wa/<profile>/audit.log. Every send + every allowlist decision + every migration is recorded. Never auto-rotated — back it up yourself.Inbound prompt-injection firewall. Inbound message bodies are wrapped in
<channel source="wa" ...>…</channel>tags before reaching Claude Code so the model can structurally distinguish "the user typed this in the terminal" from "an unknown contact sent this".Crash-safe migration. 007→008 migration uses a write-ahead marker + single
os.Renamepivot + fsync barriers. Proven by a subprocessSIGKILLinjection test that kills the process between every step and asserts zero data loss on recovery.Socket hardening. Unix socket + sibling lockfile opened with
O_NOFOLLOW(CVE-2025-68146), parent directory verified mode0700+ euid-owned,SO_PEERCREDcheck on every accept, umask-narrowed bind.
Full threat model: SECURITY.md.
Architecture
┌──────────────────────────┐
│ cmd/wa │ thin JSON-RPC client
│ (cobra, no business │ (stateless, re-invokable,
│ logic, no state) │ what scripts actually call)
└─────────────┬────────────┘
│ JSON-RPC 2.0 over
│ $XDG_RUNTIME_DIR/wa/<profile>.sock
▼
┌──────────────────────────────────────────────────────────────┐
│ cmd/wad │ composition root
│ │ (one process per profile)
│ ┌─────────────────────────┐ ┌────────────────────────┐ │
│ │ internal/app/dispatcher │◄──►│ Safety pipeline: │ │
│ │ (use cases, port-only) │ │ allowlist + rate lim │ │
│ │ │ │ + warmup + audit │ │
│ └───────────┬─────────────┘ └────────────────────────┘ │
│ │ │
│ ▼ 9 port interfaces │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ internal/adapters/secondary │ │
│ │ whatsmeow | sqlitestore | sqlitehistory | memory │ │
│ │ slogaudit | … │ │
│ └───────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
│
│ Signal Protocol ratchets +
│ WhatsApp Multi-Device websocket
▼
web.whatsapp.comHexagonal core (
internal/domain/,internal/app/) depends only on the 9 port interfaces ininternal/app/ports.go. Not one import ofgo.mau.fi/whatsmeowoutside the adapters, enforced by agolangci-lint depguardrule that is CI-blocking.Port-boundary fakes: every secondary adapter ships an in-memory twin for tests. The contract test suite (
internal/app/porttest/) runs against any adapter. No test reaches the real websocket.One daemon per profile. Feature 008 bounds the blast radius: a crash in one profile's daemon never touches another. Trade-off: ~30 MB RSS per profile.
No CGO. Ever.
modernc.org/sqliteis the only SQLite path. Enforced in the Nix flake (env.CGO_ENABLED = "0"), in GoReleaser, and in thego.modtoolchain flags.
For the full design and reliability principles, see docs/manual.md.
Command reference (at a glance)
Client (wa):
Command | Purpose |
| Scan a QR or use |
| Non-blocking connection state |
| Send a text message (allowlist + rate limiter apply) |
| Send an image/video/audio/document (over |
| Send a quoted reply that threads under a message |
| Mark a message as read |
| Add/remove a reaction |
| Moderate an already-sent message |
| Vote on a poll ( |
| Send typing / recording indicators |
| List joined groups |
| Administer a group (admin actions) |
| List chats, most-recently-active first (read-only) |
| Change chat-level state |
| Show one chat's history (paginated) |
| Filter messages by chat, media kind, direction, time window |
| Full-text (FTS5) search across all messages |
| Fetch a cursor-paginated message window |
| Export a chat oldest-first as NDJSON |
| List or trigram-search the local contact directory |
| Server-side blocklist + PN↔LID resolution |
| Read the live account privacy settings |
| Change one privacy setting (e.g. |
| List media with cache status (sha256, size, duration) |
| Resolve / lazy-fetch content-addressed media |
| Preview GC candidates as NDJSON + a reclaimable-bytes summary |
| Upload a client-local file to a remote daemon's media store; prints its sha256 for reuse with |
| Schedule future sends (pending → fired|cancelled|failed) |
| Human-review draft queue |
| WhatsApp Business labels (behind |
| Unlink every device from the account |
| Grant actions |
| Revoke all actions |
| Dump the allowlist |
| Block until an event arrives |
| Stream filtered events as NDJSON (cursor-resumable) |
| Live-tail incoming messages as NDJSON (wraps |
| Force an immediate history pull when the DB lags the phone |
| Show the on-demand sync engine state (in-flight pulls, queue depth) |
| Inspect / drop the vector index (behind |
| Non-blocking liveness probe (paired/connected/last-event) |
| Run 11 self-diagnostic checks against the local install |
| Capture a runtime profile from |
| Verify the audit-log HMAC chain |
| Show resolved feature flags (embeddings, scheduled_sends, labels) |
| Multi-profile lifecycle |
| Explicit 007→008 migration |
| Unlink device + wipe local session |
| Version, commit, build date |
| Print the upgrade command for your install method |
| Shell completion script |
Daemon (wad):
Command | Purpose |
| Run the daemon in the foreground |
| Install systemd/launchd unit for a profile |
| Remove only the specified profile's unit |
| Internal target for |
Full flag reference: docs/manual.md §6.
Inspecting the daemon (when the CLI "lies")
The daemon owns the SQLite truth; the CLI is a thin client over it. When a command's output looks wrong — a chat you expect is missing, a message count seems stale — work down this ladder. The first rung resolves almost every case without touching the database.
1. First-class discovery commands (the supported path)
These read straight from the daemon and need no SQL. They replace the old
docker cp messages.db + hand-rolled SELECT workaround:
Question | Command |
Which chats exist, most-recent first? |
|
What's in one chat, filtered? |
|
Who's in the contact directory? |
|
What media is cached on disk? |
|
What would GC reclaim? |
|
Messages on the phone but missing here? |
|
Is a sync in flight right now? |
|
Watch new messages arrive live? |
|
Add --json to any of them for NDJSON you can pipe to jq. Against a Dokku
deploy, run the same commands inside the container —
dokku enter <app> -- /usr/local/bin/wa chat list — or over an
SSH-forwarded socket with scripts/wa-remote chat list.
2. wa doctor
If the discovery commands themselves look impossible (e.g. zero chats on a
paired account), run wa doctor. It runs 11 checks — socket perms, pairing
state, on-disk layout version, audit-log size — and prints a hint: line for
every WARN/FAIL. A schema_version WARN means the on-disk layout drifted
from domain.LayoutSchemaVersion; run wa migrate to forward-migrate.
3. Raw SQLite (last resort)
The production image is gcr.io/distroless/static-debian12:nonroot — no
shell, no sqlite3, no ls/find. You therefore cannot
dokku enter <app> -- sqlite3 …, and there is intentionally no wa-debug
sidecar image (it would widen the attack surface the distroless base exists
to shrink). Instead, query a WAL-safe snapshot from the Dokku host, which
has its own sqlite3:
# messages.db lives under XDG_DATA_HOME → on the host storage mount:
DB=/var/lib/dokku/data/storage/<app>/data/wa/<profile>/messages.db # <profile> defaults to "default"
# Snapshot via the online-backup API (WAL-safe; never `cp` a live WAL DB):
ssh dokku.example.com sudo -u dokku-65532 \
sqlite3 "$DB" ".backup '/tmp/messages-snapshot.db'"
# Inspect the snapshot, not the live file:
ssh dokku.example.com sqlite3 /tmp/messages-snapshot.db \
"SELECT chat_jid, push_name, COUNT(*) AS msgs, MAX(ts) AS last
FROM messages
WHERE chat_jid LIKE '%@s.whatsapp.net'
GROUP BY chat_jid ORDER BY last DESC LIMIT 20;"On-disk layout (container path → Dokku host path under
/var/lib/dokku/data/storage/<app>):
File | Container path | Purpose |
|
| History + FTS5 |
|
| Signal session (never copy live) |
|
| Contact mirror |
media blobs |
| Content-addressed cache |
|
| On-disk layout version |
Copying a live WAL-mode DB with cp can produce a corrupt file — always go
through .backup. See the Backups section of
docs/deploy/dokku.md.
Development
# Clone
git clone git@github.com:yolo-labz/wa.git
cd wa
# Devshell (Nix users)
nix develop
# Or use your own Go toolchain (1.26+, matching go.mod)
go version
# Build
go build ./cmd/wa ./cmd/wad
# Test (race detector on by default; ~20s wall clock)
go test -race ./...
# Lint
golangci-lint run
# Format
gofumpt -w .
# Nix build + smoke test
nix build .#default && ./result/bin/wa version
# Snapshot release (local only, no publish)
goreleaser release --snapshot --clean --skip=publishWorkflow: every change lands via PR against main, commit subjects follow Conventional Commits. See CONTRIBUTING.md.
CI/CD runs on a self-hosted GitHub Actions runner pool (label set [self-hosted, dokku], with one runner — wa-sonar-runner — additionally labelled sonar). Required-check jobs: detect, lint (golangci-lint), test (race + shuffle + coverage), sonar (SonarQube scan, consumes the cover.out artifact), nix (nix flake check + nix build .#default + smoke), commitlint (PR title), Reproducibility (two-build byte-identity), OSV-Scanner (vuln DB + Go call-graph reachability via internal govulncheck), gitleaks (secret scan), CodeQL (Go + actions). Hosted runners are reserved for OpenSSF Scorecard (needs fresh image guarantees). Release workflow triggers on v* tags and publishes GoReleaser tarballs + dual SBOMs (CycloneDX 1.6 + SPDX 2.3 + Go-native per-binary) + Cosign Sigstore bundles + GitHub-native attestations to GitHub Releases. Apple notarization and Homebrew tap publication graceful-degrade when their secrets are absent.
Project status
Version | Highlights |
v2.0.2 | Hot-fix the |
v2.0.1 | Release-pipeline hot-fixes: cyclonedx-gomod path, syft CycloneDX 1.6 cap, gomod proxy off, Apple GA gate post-rc7 amendment. Broken: CLI handshake — superseded by v2.0.2. |
v2.0.0 | Parity hardening — 7 new ports + 20 P0 methods + idempotency + chat-state + blocker + privacy + profile editor + group admin + poll manager. OTel runtime metrics, fuzz, doctor. JSON-RPC frozen at |
v1.2.x | Agent-experience tier-3 release — embeddings sidecar, scheduled drafts, contact search FTS5 trigram, observability ring buffer. |
v1.0.x – v1.1.x | First production releases — supply-chain attestations, OSV-Scanner V2, OpenSSF Scorecard, Cosign signing, dual SBOMs. |
v0.x | Pre-1.0 — multi-profile, crash-safe migration, hardened systemd + launchd, all benchmarked SCs pass with 7.6×–870× headroom. |
Live backlog (deferred until a profile pin or external action exists): homebrew_casks: migration (replaces brews:, but Linuxbrew loses formula path on darwin-only casks — needs apt/rpm via nFPM as a Linux substitute first), LID/BSUID dual-keying in domain.JID (Meta June 2026 username rollout), default.pgo PGO profile (capture pipeline + commit), actions/attest migration off the attest-build-provenance@v4 wrapper.
Who this is for
One person — the maintainer. Multi-tenancy, hosted SaaS, and group-bulk-messaging use cases are explicitly out of scope. The entire safety story assumes a single-user threat model where FileVault / LUKS is the encryption boundary and wa panic is the recovery button. If that's not what you want, use one of the alternatives listed in What this is NOT.
License
Apache-2.0. The go.mau.fi/whatsmeow upstream is MPL-2.0, which is file-level copyleft and does not propagate to consumers (Mozilla MPL FAQ Q9–Q11). The Apache choice matches the precedent set by Anthropic's official Telegram channel plugin and gives an explicit patent grant.
Acknowledgements
tulir/whatsmeow— Tulir Asokan and the mautrix project, for the only WhatsApp library worth using in 2026.AsamK/signal-cli— for proving that a daemon-plus-thin-CLI architecture for an end-to-end-encrypted messenger is achievable in a single binary.aldinokemal/go-whatsapp-web-multidevice— closest prior art, solving a different shape of the problem (REST gateway vs CLI daemon).spf13/cobra+creachadair/jrpc2+modernc.org/sqlite— the three load-bearing Go libraries that make this project CGO-free, testable, and pleasant to maintain.rogpeppe/go-internal— forlockedfileandtestscript, both of which the project leans on heavily.
See also (yolo-labz ecosystem)
yolo-labz/claude-mac-chrome — Chrome automation for cross-app pipelines (e.g., LinkedIn DM → triage → WhatsApp follow-up via this daemon).
yolo-labz/linkedin-chrome-copilot — LinkedIn workflow plugin that composes with
wafor cross-channel automation.yolo-labz/kokoro-speakd — TTS daemon for spoken status feedback during long-running send batches.
Architecture deep-dives + WhatsApp-daemon design rationale: blog.home301server.com.br.
Author portfolio: portfolio.home301server.com.br.
Services
Compliance-grade AI architecture for regulated workloads — async-first, USD-denominated, LATAM-based / EN-fluent. See blog.home301server.com.br/services.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityCmaintenanceEnables AI agents to interact with WhatsApp through a Model Context Protocol server, supporting sending text messages, contacts, links, and locations via standardized tools.Last updated6MIT
- Flicense-quality-maintenanceEnables WhatsApp automation through MCP protocol, allowing users to manage sessions, send messages, handle groups/communities, and access contacts through natural language interactions with AI agents.Last updated26
- Flicense-qualityBmaintenanceMCP server that exposes a real WhatsApp account to Cursor through safe, approval-gated tools and a local Go bridge, enabling chat management, contact search, and message send with explicit confirmation.Last updated
- AlicenseBqualityBmaintenanceEnables sending messages, images, documents and more on WhatsApp directly from any MCP-compatible AI, with tools for chat management, groups, and webhooks.Last updated371MIT
Related MCP Connectors
Phone, SMS & email for AI agents — one remote MCP endpoint, OAuth login, zero install.
Give AI agents real phone numbers, messages, and voice calls via MCP.
Hosted MCP with 91 agent tools: X, domains, SEO, Maps, Trends, Search, YouTube, TikTok, and more.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/yolo-labz/wa'
If you have feedback or need assistance with the MCP directory API, please join our Discord server