Skip to main content
Glama
razvangirgiz

wazap-mcp

by razvangirgiz
██╗    ██╗ █████╗ ███████╗ █████╗ ██████╗
██║    ██║██╔══██╗╚══███╔╝██╔══██╗██╔══██╗
██║ █╗ ██║███████║  ███╔╝ ███████║██████╔╝
██║███╗██║██╔══██║ ███╔╝  ██╔══██║██╔═══╝
╚███╔███╔╝██║  ██║███████╗██║  ██║██║
 ╚══╝╚══╝ ╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚═╝

M8ven Score

WhatsApp for your AI assistant. wazap is an MCP server that puts your own WhatsApp account — chats, messages, media, contacts, groups — behind 20 tools any MCP client can call, so Claude, ChatGPT, Gemini, Cursor or Codex can read your inbox and draft your replies.

What it does

It links your account as a linked device, the way WhatsApp Web does, and keeps what it sees on this machine. Then you talk to your assistant instead of to a tool:

  • "What did I miss on WhatsApp today?" — one answer across every linked account: who is waiting on a reply, mentions, missed calls, groups condensed.

  • "Find the invoice Dan sent in spring." — search by meaning and by words at once, then open the file.

  • "What did the voice note from mama say?" — voice messages come back as text.

  • "Tell Ana I'll be twenty minutes late." — the assistant shows you the recipient and the exact words, and nothing leaves until you say yes.

Built on Baileys, which speaks the WhatsApp multi-device protocol over a WebSocket. No browser, no phone-number reseller, no account with us — there is no us: wazap runs on your machine.

Related MCP server: wa-bridge

Get started

The npm package is wazap-mcp; the command it installs is wazap.

npx wazap-mcp setup

That is the whole install. It links your account, finds the MCP clients installed on this machine, writes their config, copies the five skills where that client reads them, and tells you what to restart.

Or have your agent do it. Paste this:

Set up WhatsApp for me: run npx wazap-mcp setup --agent and follow what it prints.

Then ask your assistant: "what did I miss on WhatsApp today?"

Or the path your harness prefers

Harness

Fastest path

Claude Code

/plugin marketplace add razvangirgiz/wazap, then /plugin install wazap@wazap

Claude Desktop

download wazap-<version>.mcpb from Releases and double-click it

Gemini CLI

npx wazap-mcp connect gemini

Cursor

the Install in Cursor badge, then npx wazap-mcp skills install cursor

Codex CLI

npx wazap-mcp connect codex, then npx wazap-mcp skills install codex

A hosted agent (claude.ai, ChatGPT)

a URL it signs in to: Keep it running

Anything else

the MCP entry npx -y wazap-mcp over stdio

Install in Cursor

Each local harness registers the server; a hosted agent gets a URL. Linking the WhatsApp account is a separate, one-time step: npx wazap-mcp login, which shows a QR code to scan from Settings → Linked devices → Link a device, or prints an 8-character code with --phone +15550100.

npx wazap-mcp on its own is safe to run: it prints where you stand and what to do next, and starts no server. When something is off, npx wazap-mcp status is the first thing to run — and it is what tells you if the Node you have is too old: wazap needs 22.16 or newer on the 22 line, or 24.

Every step setup takes, every client it can write, the background service and the upgrade command are in docs/install.md.

The 20 tools

Each one in a line. What every argument means, the workflows behind them and every error code are in docs/tools.md; the assistant itself gets all of it by calling learn first.

Tool

Kind

What it does

learn

read

The guide to every tool, id format and error code. Call it first.

get_status

read

Connection, sync, linked accounts, how fresh the history is, webhook delivery, versions.

link_account

read

Pair an account from the assistant; returns the 8-character code to type into the phone.

list_chats

read

Conversations newest-first: all, unread, groups, individual or archived.

read_messages

read

Messages in a chat, paging back into the phone's history; chat_id: "status" reads the stories.

catch_up

read

"What did I miss?" across every account, in one call and within a token budget.

search

read

Messages by meaning and by words at once, narrowed by chat, sender or date.

get_message

read

One message in full: its quote, each reaction with who left it, poll votes, delivery and read receipts.

find_contact

read

Who "mama", a nickname, a group name or a number means, before anything is drafted.

get_group_info

read

Participants, admins, who may post or edit, join requests, invite link.

get_media

read

A message's media: a voice note as its transcript, a photo as an image, any file saved to disk.

wait_for_messages

read

Block up to 55 s until a message arrives, then return it with a cursor for the next call.

remember

local

Keep a note, tags and details about a person, on this machine only. Nothing changes on WhatsApp.

send_message

write

Draft a message, media, poll, location or forward — and send nothing.

confirm_send

write

Send that draft, once, after the user has seen the preview and said yes.

edit_message

write

Edit your own message, within WhatsApp's 15-minute window.

react_to_message

write

Add or remove an emoji reaction.

delete_message

write

Retract your own message for everyone, or delete any message for this account only.

manage_chat

write

Archive, pin, mute, mark read or unread, star, clear, delete, block.

manage_group

write

Create, join, rename, add, remove, promote, invite links, join requests, settings.

Voice messages become text when you switch transcription on (docs/voice.md), and search matches meaning as well as words when you switch semantic recall on (docs/recall.md). Both are off by default and both can run entirely on this machine.

Security and privacy

  • Nothing is sent without your yes. send_message only drafts: it returns the recipient and the exact text and touches no network. Only confirm_send sends, and a draft goes out at most once, even across a crash. Draft-then- confirm is a workflow, not independent proof of consent: an agent can call both tools unless the harness makes you approve the second one.

  • Read-only is a real switch. With WAZAP_READ_ONLY=1, or wazap config writes off, the write tools are not registered at all — the assistant never sees them, so it cannot message anyone from your number even by mistake. The Claude Desktop bundle ships read-only ticked.

  • Who an account may message can be pinned to a list: wazap config send allow +15550100,…, or deny for the reverse. The rules are checked when a message is drafted and again when it is confirmed (docs/send-rules.md).

  • Writes are rate limited to 20 a minute per account, because sending faster than a human is how accounts get banned.

  • The data stays here. Credentials, messages, media and notes live in ~/.wazap, 0700, with credentials 0600. There is no wazap account, no server of ours and no telemetry. What does leave the machine: WhatsApp itself; the npm registry, for the version check; Hugging Face, when you ask for a transcription or embedding model; the transcription API, only if you chose the openai provider instead of the local one; and your own webhook URL, if you configured one (docs/data.md).

  • Some people can be kept out of it. Tag someone #private and their words stay out of everything the assistant did not ask about them by name; tag them #no-catchup and their chat is skipped entirely.

  • What it does not do. There is no bulk send, no scheduler and no campaign tool. It never marks anything read on WhatsApp on its own. Text it sends goes out without a link preview, and nothing — not wazap, not Baileys — fetches the page.

Findings, threat model and the limits of each of these are in docs/security-audit.md.

Known limitations

  • The protocol is unofficial. wazap talks to WhatsApp through Baileys, a reverse-engineered implementation of the WhatsApp multi-device protocol. This is not the WhatsApp Business API, Meta does not support it, and WhatsApp can change the protocol without warning — a change can break wazap until Baileys catches up. An account that sends in bulk, or sends to people who did not ask to hear from it, can be restricted or banned, and that is not recoverable from here. What wazap does about it is the whole of the section above: sends are drafted and confirmed one at a time, writes are capped at 20 a minute per account, an account can be locked to a list of recipients or to reading only, and there is no bulk or scheduled send to reach for. None of that is a guarantee, and the risk is yours.

  • How a model behaves with the tools is measured on Claude only. The evaluation of how an assistant uses them (eval/: 58 cases, each run three times, with the sends that must never happen counted apart) has been run on Claude. ChatGPT, Gemini, Cursor and Codex connect and get the same 20 tools, but nobody has measured them yet, so what the section above promises is the server's doing, not the model's. The manual protocol for ChatGPT is eval/chatgpt-protocol.md.

  • Media keys expire. WhatsApp drops old attachments from its servers, so get_media on an old message returns MEDIA_UNAVAILABLE.

  • History is what the phone syncs. wazap sees the history WhatsApp hands the linked device, not your full phone archive. read_messages with before asks for more, within whatever WhatsApp still keeps.

  • @lid ids. Newer accounts are addressed by a privacy id rather than a phone number. wazap translates them back to phone numbers when it has learned the mapping, and passes the @lid through when it has not.

  • Names come from the phone's address book. WhatsApp delivers it as an app state sync, and only to a connection asking for it from scratch. If contacts read as phone numbers and get_status shows contacts_named: 0, find_contact asks for it once, and wazap contacts resync asks again while no server runs.

  • Calls are WhatsApp calls only. A call shows up as a message with type: "call", carrying its kind, direction, outcome and duration. WhatsApp's own call log and the missed-call notices arrive on their own; a call that starts and ends while wazap is running is recorded live, so calls placed or received while it is stopped can be missing entirely. A cellular call from the phone's dialler is never visible, on any device.

  • Your phone must stay reachable. A linked device stops receiving once the phone has been offline long enough; get_status says so in hint.

What 1.0 guarantees — which names, shapes and settings are promised not to move, and which are not — is in docs/stability.md.

Documentation

docs/install.md

Every step of setup, each client connect writes, the background service, expose, upgrading, and the five skills

docs/tools.md

The 20 tools in full: catching up, finding people, sending once, keeping someone private, and every error code

docs/voice.md

Voice messages as text: whisper.cpp here, or an OpenAI-compatible API

docs/recall.md

Semantic recall: search by meaning, with a local embedding model

docs/data.md

The data directory, the account database, wazap backup, the copy an upgrade takes, deleted and disappearing messages, and upgrading from 0.21

docs/accounts.md

Several WhatsApp accounts in one wazap, and several MCP clients on one server

docs/send-rules.md

Read-only mode, per-account send rules, link previews and media processing

docs/self-host.md

HTTP mode, systemd, Docker, tunnels, reverse-proxy trust and the OAuth server hosted agents sign in to

docs/api-and-webhooks.md

Building a product on wazap: static bearer tokens in, signed webhook events out

docs/settings.md

Every WAZAP_* setting, its default and what sets it

docs/security-audit.md

The audit report

CHANGELOG.md

What changed, release by release

Development

npm install
npm run typecheck
npm test                       # builds, then runs node --test
node test/smoke-stdio.mjs      # drives the built binary over MCP stdio
npm run dev -- status          # run from source with tsx

npm test needs no WhatsApp session. The stdio smoke test spawns the built binary against a throwaway data directory and checks that an unlinked install still answers initialize, tools/list and get_status.

AGENTS.md is the contributor's map: the layout, the rules that must never break, the release procedure and the knobs only tests use. Issues and pull requests go to github.com/razvangirgiz/wazap.

MIT licensed.

Available Tools

20 tools
catch_upCatch up on what the user missedA
Read-only

What the user missed, all accounts, within budget_tokens: waiting (every open ask of 14 days, whatever the window), mentions, calls, people, groups, stories. account_id narrows it to one account; get_status names them. The mark moves first; a lost answer is since: "previous". more.cursor: the rest.

ParametersJSON Schema
NameRequiredDescriptionDefault
hoursNoThe last N hours instead; never moves the mark
sinceNo"last" (default); "previous" repeats that catch-up; or an ISO date or time from the last 14 days
cursorNomore.cursor
includeNoOnly these sections; the mark then stays
account_idNoAccount id
budget_tokensNoAnswer length in tokens

Output Schema

ParametersJSON Schema
NameRequiredDescription
moreYesSet when entries are left: call catch_up again with more.cursor
notesNoCaveats to act on or tell the user
directYes
footerYesOn the last page: what the entries leave out
groupsYes
windowYes
storiesYes
waitingYes
accountsYes
addressedYes
account_idYes
missed_callsYes
approx_tokensYes

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description explains the non-idempotent behavior of moving the mark and the consequence of losing an answer (use since:'previous'), which goes beyond annotations. It also clarifies budget_tokens and cursor usage. Annotations (readOnlyHint true, destructiveHint false) are consistent, and the description adds meaningful behavioral detail without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single run-on sentence with heavy jargon ('the mark moves first', 'a lost answer is since: previous'). It is concise in length but not well-structured or front-loaded; the core purpose is somewhat buried. The cryptic phrasing reduces readability despite the compact size.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with six optional parameters and non-trivial behavior (mark movement, pagination, token budget), the description covers the essential operational details: sections, account narrowing, cursor handling, and the token limit. The output schema exists to handle return values. It lacks error handling or edge cases, but overall it is sufficiently complete for an advanced tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 100% schema description coverage, the description enriches parameter understanding: it explains 'since' options, the mark movement, and the meaning of 'more.cursor'. It also lists the sections returned, which aligns with the include parameter even though terminology differs slightly (e.g., 'mentions' vs 'addressed'). This adds value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear purpose: fetching what the user missed across all accounts, listing sections like waiting, mentions, calls, people, groups, stories. It distinguishes from siblings by focusing on aggregated missed content, though it does not explicitly name alternatives. The title reinforces this, so it is not a tautology.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives some usage context, such as using account_id to narrow to one account and mentioning get_status for names, plus the mark movement behavior and cursor pagination. However, it does not explicitly state when to use this tool versus alternatives, nor does it provide exclusions or prerequisites. The guidance is implicit rather than direct.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

confirm_sendSend a drafted WhatsApp messageA
Idempotent

Send a draft the user approved — this text, this recipient: the only call that sends, once per draft. A yes about something else: show the preview again and ask. Expired, missing or stale: draft again, show the new preview, ask again. SEND_OUTCOME_UNKNOWN: read_messages, never redo it unasked.

ParametersJSON Schema
NameRequiredDescriptionDefault
draft_idYesFrom send_message
account_idNoAccount id

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=false, idempotentHint=true, and openWorldHint=true. The description adds valuable behavioral context beyond annotations: it clarifies the idempotency as 'once per draft,' specifies handling for stale/missing drafts, and warns 'never redo it unasked.' It also states that this is the only sending call, which is not present in annotations. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: the first sentence states the core action and its exclusive nature, followed by three terse edge-case rules. Every sentence earns its place, with no filler or repetition. The structure is scannable and highly efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has no output schema, so the description must cover behavior. It addresses the main action, when not to use, and fallback actions for exceptional cases. It does not state what the tool returns on success (e.g., a message ID), but that is often implied and not critical for correct invocation. Given the edge-case richness, the description is nearly complete for an agent to decide and call it appropriately.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%: draft_id is described as 'From send_message' and account_id as 'Account id.' The description itself does not add further parameter details, but it does imply the draft carries text and recipient, which relates to draft_id. With full schema coverage, a baseline of 3 is appropriate; the description doesn't need to compensate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Send a draft the user approved' with the exact scope 'this text, this recipient.' It explicitly distinguishes from siblings by calling itself 'the only call that sends, once per draft,' which separates it from send_message and other drafting tools. The purpose is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear when-to-use guidance: only for an approved draft, and provides explicit when-not-to-use conditions: 'A yes about something else' or 'Expired, missing or stale' should trigger preview re-shows instead of sending. It also names a fallback for unknown outcomes ('read_messages'). While it doesn't enumerate all sibling tools, it gives concrete decision rules that route the agent correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_messageDelete a WhatsApp messageA
DestructiveIdempotent

Delete a message; confirm with the user first. for_everyone: true retracts it for everyone within 2 days: the account's own message, or anyone's in a group where it is admin. for_everyone: false removes any message from the linked account's devices only.

ParametersJSON Schema
NameRequiredDescriptionDefault
account_idNoAccount id
message_idYes
for_everyoneYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
account_idYes
message_idYes
for_everyoneYes

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructive behavior, but the description adds meaningful context: the 2-day retraction window, the admin-permission condition for group messages, and that for_everyone:false only affects the linked account's devices. This goes well beyond the structured hints and helps set expectations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three clauses with no filler; the mandatory user-confirmation is front-loaded, and the for_everyone branch is expressed compactly. Every sentence adds distinct value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a rich behavioral description and an output schema present, the core invocation requirements are covered. The main remaining gap is that account_id's role is never explained, and there's no explicit statement of what happens if it is omitted. Still, for a destructive tool with strong annotations, this is close to complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description thoroughly explains for_everyone behavior, which the schema leaves undocumented, and indirectly clarifies message scope as 'the account's own message' or 'anyone's in a group.' However, account_id and message_id receive no real semantic help beyond the schema's minimal 'Account id' and name/minLength, so the compensation is incomplete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource ('Delete a message') and immediately clarifies the operation's scope via the for_everyone flag. The local-vs-everyone distinction separates it from siblings like edit_message and send_message even though those aren't named.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly instructs the agent to confirm with the user first, which is a clear prerequisite before invoking. It also states when for_everyone is valid (true within 2 days, own message or admin in group) versus local-only removal (false), giving condition-based guidance. It doesn't explicitly name alternative tools, but it defines the choice space.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

edit_messageEdit a WhatsApp message you sentA
DestructiveIdempotent

Replace the text of a message the linked account sent. WhatsApp allows it for 15 minutes after sending; later, send a correction instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
textYes
account_idNoAccount id
message_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
textYes
chat_idYes
timestampYes
account_idYes
message_idYes

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already signal destructiveHint=true and readOnly=false, so the description's 'replace' is consistent and not a contradiction. It adds the platform constraint of 15 minutes, but does not disclose behavioral details such as whether recipients see an edited indicator or what happens on failure. With annotations carrying the safety profile, the description contributes only moderate additional transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no filler. The core purpose is front-loaded, and the time-limit/fallback guidance is contained in a single follow-up sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simple mutation scope, existing output schema, and annotations, the description covers the essential operational constraint (15-minute window), the ownership constraint (linked account), and the fallback path. It does not detail error semantics, but the schema and annotations fill most of the remaining context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 33%, and the description gives only implicit semantics: 'text' maps to the replacement content, 'message' to message_id, and 'linked account' to the account context. It adds some meaning beyond the schema, but does not explicitly define the relationship of account_id or the expected format of message_id.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific operation: replace the text of an existing message sent by the linked account. This clearly distinguishes it from siblings like send_message and delete_message, and the phrasing 'linked account sent' narrows the target.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states the 15-minute edit window and instructs to send a correction instead afterward. This gives a clear when-to-use and when-not-to-use condition, though it does not explicitly name the sibling tool (e.g., send_message) or list other exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_contactFind who the user meansA
Read-onlyIdempotent

Who a name, nickname, relationship ("mama"), group, number or id means, before drafting. resolved: contact.chat_id, with number, note, tags, details and, in a write session, context. ambiguous or not_found: ask the user; never send to a guess. A name on several accounts: see fix. tag: its people.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagNoList everyone filed under this tag instead
kindNoany
nameNoWhat the user calls them ("Ana", "mamei", "fotbal"), or a number or id
limitNoAmbiguous: at most 5 per account; a tag list: up to 50
qualifierNoTells two apart: "contabilitate", a group, the last 4 digits
account_idNoAccount id
include_contextNoRecent messages and the user's style, when resolved in a write session

Output Schema

ParametersJSON Schema
NameRequiredDescription
fixNoWhat to do next, when not resolved
nextNoResolved: how a message to them starts
notesNoCaveats to act on or tell the user
queryYes
statusYes
closestNoOnly when not_found
contactNoOnly when resolved
contextNoOnly when resolved, in a session that can write: what a draft to them is written after
omittedNoOnly when listed and cut by limit: how many more on each account
contactsNoOnly when listed: everyone filed under the tag
can_draftNoResolved in a session that cannot send
account_idNoThe account that answered; null when several accounts were searched and none answered alone
candidatesNoOnly when ambiguous; best first
accounts_searchedNo
accounts_unavailableNo

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already supply readOnly/idempotent/non-destructive hints, and the description adds genuinely useful behavior: resolved results include chat_id plus notes/tags/details/context, ambiguity triggers a user question rather than a guessed send, tag mode returns people, and multi-account conflicts are flagged. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact, information-dense, and front-loaded with the core purpose. The telegraphic fragments and the unclear 'see fix' reference slightly hurt readability, but no sentence is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter lookup tool, the description covers the main usage flow, disambiguation behavior, tag mode, and write-session context, and an output schema exists so return values need not be spelled out. The only real gap is that the 'fix' handling for same-name-on-several-accounts is referenced but not defined.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is high (86%) and each parameter already has a meaningful description, so the main description does not need to re-document them. It adds some outcome context (what resolved means, tag mode, ambiguity limits), but not significant per-parameter meaning beyond the schema, earning the baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action: resolve what a name, nickname, relationship, group, number, or ID refers to before drafting, and names the resolved output (contact.chat_id). This clearly separates contact resolution from sibling messaging/chat tools such as send_message or list_chats.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit usage timing ('before drafting') and a firm rule for ambiguous/not_found results: ask the user and never send to a guess. It does not explicitly name sibling alternatives such as search or list_chats, and the 'see fix' reference is not self-contained, so the alternative-selection guidance is slightly incomplete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_group_infoGet WhatsApp group infoA
Read-onlyIdempotent

A group's name, description, owner and participants (up to 500), whether the account is admin, its settings (info_locked, member_add_mode, join_approval, disappearing_seconds), its community, and the invite link for an admin. Call it before manage_group.

ParametersJSON Schema
NameRequiredDescriptionDefault
group_idYes<id>@g.us
account_idNoAccount id

Output Schema

ParametersJSON Schema
NameRequiredDescription
nameYes
ownerYes
chat_idYes
communityNo
account_idYes
created_atYes
i_am_adminYes
descriptionYes
info_lockedYes
invite_linkNo
participantsYes
join_approvalYes
member_add_modeYes
announcement_onlyYes
participant_countYes
disappearing_secondsYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds value by specifying the conditional nature of the invite link ('for an admin') and the participant limit (up to 500), which are behavioral details not captured in annotations. It does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that front-loads the key data returned, then appends a usage instruction. Every phrase earns its place, with no filler. It is concise yet complete.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema exists and annotations cover read-only/idempotent behavior, the description covers what the tool returns, when to use it, and a sequencing note. Nothing essential is missing for an agent to correctly invoke this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, with both group_id and account_id documented. The description does not add extra meaning beyond the schema—it mentions group info but not parameter-specific syntax or constraints. With full schema coverage, the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('get') and resource ('group info'), then enumerates the exact fields returned (name, description, owner, participants, admin status, settings, community, invite link). It clearly distinguishes itself from sibling tools like manage_group and get_status by listing what it retrieves and by the explicit 'Call it before manage_group' directive.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'Call it before manage_group,' giving a clear precondition and usage context. This directly tells an agent when to invoke this tool versus alternatives, leaving no ambiguity about sequencing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_mediaGet the media of a WhatsApp messageB
Read-only

What a message's media holds: a voice note or audio as its transcript (kept once made; an API provider bills it), or with save_to its file; a photo attached as an image; any file saved at path on the machine running wazap. MEDIA_UNAVAILABLE: WhatsApp no longer has it.

ParametersJSON Schema
NameRequiredDescriptionDefault
save_toNoAbsolute directory; default <data-dir>/media. A recording: its file, and no new transcript
languageNoWhat is spoken, e.g. "ro"
account_idNoAccount id
message_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
mimeNo
pathNo
sizeNo
typeYes
senderYes
captionYes
filenameNoThe name it was saved under
account_idYes
message_idYes
transcriptNo
image_attachedNoThe photo, or a small preview of it, is attached
original_filenameYes
transcript_unavailableNo

TDQS

B3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds valuable behavior beyond the annotations: transcripts are 'kept once made' and 'an API provider bills it' (a cost/caching trait), save_to writes media to local disk, and MEDIA_UNAVAILABLE is described as a possible error when WhatsApp no longer retains the media. These details are not in the annotations and are context-rich. Nothing contradicts the readOnlyHint/destructiveHint flags.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short (about 55 words) and contains no fluff, but it is structured as a dense, semicolon-packed run-on that is hard to parse quickly. The MEDIA_UNAVAILABLE sentence is a useful standalone component, yet the overall ordering muddles the main action. It is concise without being cleanly structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema and annotations available, the description does not need to explain return values. However, it fails to clarify the role of account_id, the meaning of message_id, or when to use language vs save_to. It does cover the media type possibilities and the MEDIA_UNAVAILABLE error, but an agent would still have to infer significant context from parameter names and external knowledge.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 75%, so the heavy lifting is done by the schema. The description adds a little context for save_to (its file) and the transcript/language relation, but the required message_id has no schema description and the description does not compensate. This is an acceptable baseline-3 case.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explains what a message's media can hold (transcript, file, photo, saved path) but never states a clear verb phrase like 'fetches' or 'returns' – it is phrased as a noun fragment. The title 'Get the media of a WhatsApp message' is clearer than the description. It implies media retrieval but does not explicitly differentiate from siblings like get_message.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus alternatives such as get_message, read_messages, or search. No exclusions or 'instead of' notes are present; usage is only weakly implied by the resource being a message's media. With many siblings, this is a notable gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_messageGet one WhatsApp message in fullA
Read-onlyIdempotent

One message in full: the message it quotes, each reaction with who left it, poll votes and event answers by person, its media, and on the user's own messages who it reached and who read it. Without account_id the id is looked for on every account.

ParametersJSON Schema
NameRequiredDescriptionDefault
account_idNoAccount id
message_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
textYes
chat_idYes
timestampYes
account_idYes
message_idYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering safety. The description adds behavioral context beyond that: it specifies exactly what data is retrieved (reactions, poll votes, etc.) and describes the fallback behavior when account_id is omitted. It does not discuss error handling or auth requirements, but given the annotations cover the safety profile, this is sufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence plus a short note. It is concise and front-loaded with the core purpose ('One message in full'). Every clause adds value, and there is no fluff. The structure is efficient and easily scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is complete enough for an agent to call this tool correctly. It lists all the components of the full message, describes the account_id fallback, and the output schema exists (as indicated by 'Has output schema: true'), so the return format is covered by the schema. The only minor gap is error handling (e.g., what happens if the message is not found), but that is not critical for correct invocation. The description, combined with annotations and output schema, provides sufficient context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 50% (only account_id has a description: 'Account id'). The description adds meaningful semantics for account_id by explaining the lookup behavior when omitted. However, message_id has no description in the schema and is only implied by the tool name. The description does not provide format or syntax details for either parameter beyond the behavioral note. It partially compensates for the coverage gap but not fully.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: retrieving a single WhatsApp message in full detail. It enumerates exactly what is included (quoted message, reactions, poll votes, event answers, media, read receipts) which distinguishes it from siblings like read_messages (which likely returns multiple messages) or get_media (which only fetches media). The verb 'get' and resource 'message' are explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear usage context: this is for full message details, and the note about account_id explains a key behavior ('Without account_id the id is looked for on every account'). However, it does not explicitly state when NOT to use this tool versus alternatives like read_messages or search, nor does it name any sibling tools. The context is clear but lacks explicit exclusions or alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_statusGet the WhatsApp connection statusA
Read-onlyIdempotent

Whether the account works: status (connected, not_linked, linking with its pairing code…), sync, how fresh the history is, webhook delivery, versions. accounts lists every account, with default. Call it on NOT_CONNECTED, NOT_LINKED or SYNC_IN_PROGRESS.

ParametersJSON Schema
NameRequiredDescriptionDefault
account_idNoAccount id

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds useful context about what the status includes and when to call it, but it does not disclose details like what the default account behavior is or what 'fresh' history means. It neither contradicts annotations nor adds much deeper behavioral richness.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact, front-loaded with the core purpose, and the trigger condition is placed at the end as a natural action item. The enumeration of status facets is dense but each item earns its place; no filler sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only tool with one optional parameter and no output schema, the description covers what the status includes and when to call it. The only real gap is that it never explicitly states what happens when account_id is omitted, though 'with default' hints at it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema documents account_id at 100% coverage, so the description does not need to repeat it. The phrase 'accounts lists every account, with default' hints at default-account behavior for the optional parameter, but it is ambiguous and adds only marginal value over the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear verb+resource ('get status') and enumerates the specific facets it covers: connection state, sync, history freshness, webhook delivery, versions. This differentiates it from the chat/message-oriented siblings and leaves little ambiguity about what get_status reports.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly gives conditional trigger conditions: 'Call it on NOT_CONNECTED, NOT_LINKED or SYNC_IN_PROGRESS.' It does not explicitly name sibling alternatives or exclusions, but the trigger guidance is concrete and actionable, so it is above average.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

learnLearn how to use the WhatsApp toolsA
Read-onlyIdempotent

The guide to these tools: ids, account_id with several accounts, the workflows, the message shape and what to do about each error code. Read it once, before the other tools; it never touches WhatsApp.

ParametersJSON Schema
NameRequiredDescriptionDefault
account_idNoAccount id

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior. The description adds useful context beyond the annotations: the tool is a pure documentation read that has no effect on WhatsApp. This reinforces safety and clarifies that repeated reads are harmless.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly packed sentences with no wasted words. The core purpose is front-loaded, and the usage instruction is immediate and actionable. Topics are enumerated efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a documentation/guide tool, the description fully covers what the tool is, what topics it contains, when to call it, and that it has no side effects. The optional account_id parameter is the only input, and the description provides enough context for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the single account_id parameter, but its schema description is minimal ('Account id'). The tool description adds meaningful context by noting that account_id matters 'with several accounts,' which explains when the parameter is relevant.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear purpose: a guide to the WhatsApp tools covering IDs, account_id, workflows, message shape, and error codes. It also distinguishes itself from the sibling operational tools by saying it 'never touches WhatsApp' and should be read 'before the other tools.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly tells the agent when to use it: 'Read it once, before the other tools.' It also clarifies what it is not for by stating it never touches WhatsApp, implicitly routing operational tasks to sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_chatsList WhatsApp chatsA
Read-onlyIdempotent

Conversations, most recently active first: chat_id, name, type, unread count, last message, and whether archived, pinned, muted or left. Use it to find a chat_id.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
filterNo"all" leaves out archivedall
account_idNoAccount id

Output Schema

ParametersJSON Schema
NameRequiredDescription
syncYes
chatsYes
countYes
filterYes
account_idYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds behavioral context beyond the annotations by disclosing sort order ('most recently active first') and the chat states surfaced (archived, pinned, muted, left). The annotations already cover read-only, idempotent, and non-destructive behavior, lowering the burden on the description.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no filler: the first front-loads the key ordering and return fields, and the second gives the direct use case. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a low-complexity, read-only list tool, the combination of this description, the rich annotations, and the output schema gives an agent everything needed to call it correctly. No necessary prerequisites, return-value details, or edge behaviors are missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description itself adds little about limit, filter, or account_id. However, the schema already documents filter and account_id with descriptions, and limit has clear bounds and a default, so the parameter meaning is adequately covered without the description compensating further.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific outcome—'Conversations, most recently active first'—and enumerates the exact fields returned: chat_id, name, type, unread count, last message, and archived/pinned/muted/left state. It closes with a concrete intended use ('Use it to find a chat_id'), which clearly distinguishes it from the messaging and management siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description states a clear use case: finding a chat_id. It does not name sibling alternatives or explain when not to use it, so it stops short of full routing guidance, but the context is clear enough for an agent to select it appropriately.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

manage_chatManage a WhatsApp chatA
Destructive

Change a chat on WhatsApp at once, with no draft: archive, pin, mute, mark_read or mark_unread; pin_message (for everyone) or star_message on a message_id; clear or delete it for the linked account; block a person. Say what will change and wait for a yes.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionYes
chat_idYesChat id, or a phone number
pin_hoursNopin_message: 168 by default
account_idNoAccount id
message_idNopin_message, star_message and their undo; in chat_id
mute_hoursNomute: 8 by default

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already signal destructive and non-idempotent behavior, so the description's job is to add context. It adds meaningful behavioral detail: actions happen 'at once, with no draft', pin_message affects 'everyone', clear/delete is scoped to 'the linked account', and user confirmation is required before changes. These are useful traits not captured in structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single efficient sentence that front-loads the action list and ends with the critical confirmation instruction. There is no filler, though the phrase 'at once, with no draft' is slightly ambiguous and could have been clearer or omitted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a multi-action, destructive tool with six parameters and no output schema, the description covers the key invocation context: what actions are available, the account scope, the need for message_id for certain operations, and the confirmation requirement. It does not describe return values or error behavior, but those are less critical given the schema already covers parameter details.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is high (83%), so the schema already documents chat_id, account_id, message_id, pin_hours, and mute_hours. The description adds some semantic clarification — pin_message applies 'for everyone', star_message operates on a message_id, and clear/delete applies to the linked account — but does not deeply enrich the parameter understanding beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb ('Change a chat') and enumerates the concrete actions it performs (archive, pin, mute, mark_read, etc.), which is far more specific than the title alone. It doesn't explicitly contrast itself with sibling tools like send_message or manage_group, but the action list makes the resource and scope unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context for when to use the tool: when a chat-level change is needed (archive, pin, mute, read state, message pin/star, clear/delete, block). It also includes an important process instruction — 'Say what will change and wait for a yes' — which tells the agent how to invoke it safely. It does not explicitly state when not to use it or point to alternatives, so it misses the top score.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

manage_groupManage a WhatsApp groupA
Destructive

Create a group, join one from an invite (preview first, then confirm: true), or administer one: members, name, description, photo, invite link, join requests, settings, leave. Most actions need admin. Every change shows to all members at once: say what will change, wait for a yes.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoset_picture: public image URL
valueNoThe name (create, set_subject) or description; "on"/"off"; set_add_mode "admins"/"all"; set_disappearing "off"/"24h"/"7d"/"90d"
actionYes
inviteNojoin: a chat.whatsapp.com link or its code
confirmNojoin: true joins, after the user said yes to the preview
group_idNo"<id>@g.us"; every action but create and join
file_pathNoset_picture: local JPEG, PNG or WebP
account_idNoAccount id
message_idNojoin: an invite message instead
participant_idsNocreate, add, remove, promote, demote, approve or reject

Output Schema

ParametersJSON Schema
NameRequiredDescription
nameNo
nextNojoin preview: the step after the user's yes
actionYes
statusNojoin: preview joins nothing
appliedNo
group_idYes
account_idYes
descriptionNo
invite_linkNo
participantsNo
join_approvalNo
join_requestsNo
profile_pic_urlNo
participant_countNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Although annotations already declare destructiveHint=true and readOnlyHint=false, the description adds valuable behavioral detail beyond those flags: 'Most actions need admin' and 'Every change shows to all members at once: say what will change, wait for a yes.' It also discloses the confirm-before-join flow with 'preview first, then confirm: true,' which is exactly the kind of side-effect transparency an agent needs for a social, visible mutation tool. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no filler. The first sentence front-loads the tool's capabilities, and the second delivers the critical behavioral warning. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a broad tool with 21 enum actions and 10 parameters, the description gives a high-level map of capabilities plus the essential safety/social rules. The output schema exists, so return values need no explanation. It could be slightly more complete by steering read-only group lookups to get_group_info, but the description is sufficient for an agent to use it safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 90%, so the schema carries most parameter meaning. The description adds important semantic context for the confirm parameter by tying it to user consent: 'preview first, then confirm: true' and 'wait for a yes.' This goes beyond the schema's bare 'join: true joins, after the user said yes to the preview' and reinforces how the parameter should be used.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses specific verbs and resources: 'Create a group, join one from an invite ... or administer one: members, name, description, photo, invite link, join requests, settings, leave.' This clearly differentiates it from siblings like manage_chat and get_group_info by scoping it to group-level administration. It is not a tautology and communicates the tool's full intent.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives practical context: 'Most actions need admin' and 'Every change shows to all members at once: say what will change, wait for a yes.' This tells the agent when it is appropriate to invoke the tool and what interaction pattern to follow. It does not explicitly name alternatives or exclusion conditions, but the group-vs-chat scope and admin caution make usage context clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

react_to_messageReact to a WhatsApp messageA
Idempotent

React to a message with one emoji, or pass "" to take your reaction off.

ParametersJSON Schema
NameRequiredDescriptionDefault
emojiYes
account_idNoAccount id
message_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
emojiYes
account_idYes
message_idYes

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds a useful non-obvious behavior: an empty string removes the reaction. It does not, however, state whether an existing reaction is replaced or what happens when removing a reaction that does not exist, leaving part of the behavior to inference.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, tight sentence conveys the primary operation and the important edge-case behavior with no filler. The key constraint is front-loaded and immediately actionable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple three-parameter tool with an output schema and annotations covering idempotence and non-destructiveness, the description is nearly sufficient. It explains the emoji special case and leaves message_id and account_id inferable from their names; a note on the optional account_id's default would make it fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description meaningfully clarifies the emoji parameter: exactly one emoji is allowed, and an empty string requests removal. The schema only describes account_id as 'Account id' and leaves message_id and emoji without descriptions, so the description only partially compensates for the 33% coverage; the remaining parameters rely on their names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a concrete action ('React to a message') with an explicit constraint ('one emoji') and a distinct removal mode ('pass "" to take your reaction off'). This clearly separates it from siblings like send_message, edit_message, and delete_message.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended use is implied: call this when you want to add or remove an emoji reaction on a message. However, it names no sibling alternatives and gives no when-not-to-use guidance, so the agent must infer the selection context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_messagesRead messages from a WhatsApp chatA
Read-onlyIdempotent

Read one chat, oldest to newest: the latest messages, or older ones with before (wazap asks the phone when the local history runs out). chat_id "status" reads the stories people posted, newest first, from the last hours (at most a day); they show nowhere else.

ParametersJSON Schema
NameRequiredDescriptionDefault
hoursNo"status" only: how far back, 24 by default
limitNo
typesNoOnly these types; limit counts them, so ["call"] gives that many calls
beforeNoThe oldest message_id you have
chat_idYesChat id from another tool, a phone number, or "status" for stories
account_idNoAccount id
include_previewsNoAttach a small image of each photo, up to 12

Output Schema

ParametersJSON Schema
NameRequiredDescription
syncYes
countYes
hoursNo
notesNoCaveats to act on or tell the user
olderNobefore ran past the local history: the phone was asked, and sent this many
typesNo
chat_idYes
omittedNoOlder stories left out by limit
messagesYes
account_idYes
preview_countYes
unconfirmed_sendsNoSends WhatsApp has not echoed yet: outcome unknown, not failed

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds meaningful behavioral details: ordering (oldest to newest), the special 'status' mode behavior (newest first, limited to last hours up to a day), and the fact that it may query the phone when local history runs out. It also notes that stories appear only here, which is important context. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a compact two-sentence layout, front-loaded with the core behavior (read one chat oldest to newest), then covering the 'before' parameter, then the 'status' special case. Every clause adds meaning, and the structure is logical: main use, then variations. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (7 parameters, multiple modes, special 'status' behavior), the description covers the key usage scenarios (latest messages, older via before, status stories) and provides enough context for an agent to call it correctly. The output schema exists, so return values are already defined. Missing details like exact pagination behavior or limit default are in the schema, and the description handles the non-obvious parts.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 86%, with most parameters having descriptions (hours, types, before, chat_id, include_previews). The description adds extra meaning for key parameters: 'before' is clarified as the oldest message_id you have, 'status' chat_id is explained, and 'types' is explained with an example and the behavior that the limit counts them. Limit has no description in schema, but the description doesn't explicitly cover it, yet the overall value added is high.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it reads messages from a chat, with ordering (oldest to newest) and a special 'status' mode for stories. It distinguishes itself from siblings like get_status and get_message by covering both regular chats and the status feed, and mentions a unique capability (fetching older messages via 'before') that other tools likely lack.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use 'status' (for stories, which 'show nowhere else') and mentions bridging local history gaps via 'before', but it doesn't explicitly state when NOT to use this tool versus alternatives like search, get_message, or wait_for_messages. It implies usage for reading messages but lacks exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

rememberRemember something about a personA
Idempotent

Keep what the user says about someone, locally, never on WhatsApp: a note, tags, details find_contact matches ({"relatie": "mama"}), or handled: true for an ask dealt with elsewhere. #private keeps their words out of what you did not ask about them by name; #no-catchup keeps them out of catch_up.

ParametersJSON Schema
NameRequiredDescriptionDefault
noteNo"" removes it
fieldsNoe.g. {"nickname": "Mișu", "role": "contabil"}; "" deletes a key
chat_idYesChat id, or a phone number
handledNoOff catch_up's waiting until they write again
add_tagsNoe.g. ["client"]
account_idNoAccount id
remove_tagsNo
remove_fieldsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
nameYes
noteNo
tagsNo
fieldsNo
numberNo
chat_idYes
handledNoThe ask taken off the waiting list; null when nothing was open
account_idYes
is_businessNo
is_my_contactNo

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds meaningful behavioral context beyond the annotations: data is stored locally and never on WhatsApp, and the '#private' and '#no-catchup' tags control future retrieval behavior. This is genuinely useful information that the annotations alone do not convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loads the core purpose before explaining special flags. It is slightly dense and could be more readable, but every part adds meaningful information without unnecessary filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema, 75% schema coverage, and annotations, the description covers the essential purpose, privacy behavior, and special handling for catch-up and private queries. The main gap is the lack of explicit differentiation from the 'learn' sibling, but the tool is still usable without that clarification.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already high at 75%, so the baseline is 3. The description adds value by giving concrete examples for 'details' ('{"relatie": "mama"}'), explaining 'handled: true' as marking an ask dealt with elsewhere, and clarifying the privacy/catch-up semantics of the special tags.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies a specific action ('Keep what the user says about someone') and resource (person-related memory), and it adds important scope with 'locally, never on WhatsApp.' It also references the 'find_contact' and 'catch_up' contexts, which helps distinguish it from those siblings, though it does not explicitly contrast it with the 'learn' sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides useful context for when to set 'handled: true' and how '#private' and '#no-catchup' affect behavior, but it does not explicitly explain when to prefer this tool over alternatives like 'learn' or when not to use it. Usage is implied rather than directly stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_messageDraft a WhatsApp messageA

Drafts text, media, polls, locations, forwards; sends nothing. Call it as soon as you have recipient and text: it returns draft_id and preview (recipient, number, exact text). Show that preview; confirm_send only on a yes to this text and recipient — a send in the same request is that yes.

ParametersJSON Schema
NameRequiredDescriptionDefault
asNoMedia: a plain document, a voice note, a looping GIF
urlNoMedia: public http(s) URL
textYesThe message, or the caption, poll question or place name; "" for a forward, a voice note or audio
addressNoLocation: shown under the name
chat_idYesChat id, or a phone number
forwardNoForward this message; text ""
optionsNoPoll answers
latitudeNo
reply_toNo
file_pathNoMedia: absolute path on the machine running wazap
longitudeNo
account_idNoAccount id
mention_idsNoChat ids to @-mention; write @<number> in text for each
multi_selectNoPoll: several answers allowed

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only signal not read-only, not idempotent, and not destructive. The description adds critical behavior beyond that: no message is sent, a draft_id and preview are returned, and the preview must be shown to the user. It doesn't cover permissions or error cases, but the primary side effect and workflow are clearly disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two information-dense sentences with no filler. The first sentence front-loads the core identity ('Drafts... sends nothing') and the second packs the entire invocation workflow. Slightly dense, but every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, but the description compensates by stating the return values (draft_id and preview) and the confirmation protocol. All 14 parameters are schema-documented, and the description covers the essential call conditions and the handoff to confirm_send. Minor gaps like media URL/path constraints are already handled by the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 79%, with most parameters already well-described in the schema (text, url, as, options, address, etc.). The description maps content types to parameter groups ('media' → as/url/file_path, 'polls' → options/multi_select) but adds no per-parameter detail beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb 'Drafts' and resource 'WhatsApp message', then enumerates the exact content types (text, media, polls, locations, forwards). The explicit phrase 'sends nothing' sharply distinguishes this from the sibling confirm_send, so an agent can tell them apart immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use guidance: 'Call it as soon as you have recipient and text'. It also names the alternative tool (confirm_send) and specifies the condition for using it: only after the user confirms the exact text and recipient. The same-request send nuance is also spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wait_for_messagesWait for new WhatsApp messagesA
Read-onlyIdempotent

Wait for messages from other people, up to timeout_seconds, and return them with a cursor: pass it to the next call so nothing that lands between calls is missed. addressed_to_me wakes only for direct messages, mentions and replies to the user. For agents that stay on the line.

ParametersJSON Schema
NameRequiredDescriptionDefault
cursorNoFrom the previous call
chat_idNoChat id, or a phone number
account_idNoAccount id
addressed_to_meNo
timeout_secondsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
countYes
cursorYesPass to the next call
messagesYes
timed_outYes
account_idYes
cursor_resetYesThe cursor was from another run; the wait started now

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and non-destructive behavior. The description adds value beyond these by explaining cursor semantics ('nothing that lands between calls is missed') and the exact behavior of addressed_to_me (wakes only for direct messages, mentions, replies). No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core action, no filler. Every clause contributes: the wait behavior, timeout, cursor use, filter semantics, and intended use case. Highly efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return format is not required. The description covers waiting, timeout, cursor handling, and filter behavior. An agent has everything needed to call it correctly and integrate it into a polling loop. No critical gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 60% — cursor, chat_id, and account_id have descriptions, but addressed_to_me and timeout_seconds do not. The description explicitly explains both: timeout_seconds via 'up to timeout_seconds' and addressed_to_me via its wake filter. This fully compensates for the undocumented parameters, going beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'wait' with resource 'messages from other people' and a timeout. It distinguishes itself from read_messages by emphasizing waiting/blocking, and mentions the cursor for continuity. The purpose is specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'For agents that stay on the line' provides context for when to use this tool, and the cursor instruction implies a polling loop. However, it does not explicitly state when not to use it (e.g., for reading existing messages, use read_messages instead). The guidance is implied rather than explicit, so a 4 is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 43 tool updatesv1.0.3
    • Addedcatch_up
    • Changedconfirm_send2 fields changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
      • changedInput schema / properties / draft_id / description
        Previous value: -"The draft_id returned by a send_* tool"New value: +"From send_message"
    • Removedcreate_group
    • Changeddelete_message4 fields changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
      • removedInput schema / properties / for_everyone / description
        Removed value: -"Required. true retracts it for everyone in the chat; false deletes it for the linked account only"
      • removedInput schema / properties / message_id / description
        Removed value: -"Message id from read_messages / search_messages / get_message, e.g. \"false_4072...@s.whatsapp.net_3EB0...\""
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "account_id": {
        +      "type": "string"
        +    },
        +    "for_everyone": {
        +      "type": "boolean"
        +    },
        +    "message_id": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "message_id",
        +    "for_everyone",
        +    "account_id"
        +  ],
        +  "type": "object"
        +}
    • Removeddownload_media
    • Changededit_message4 fields changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
      • removedInput schema / properties / message_id / description
        Removed value: -"A message the linked account sent"
      • removedInput schema / properties / text / description
        Removed value: -"The replacement text"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "account_id": {
        +      "type": "string"
        +    },
        +    "chat_id": {
        +      "type": "string"
        +    },
        +    "message_id": {
        +      "type": "string"
        +    },
        +    "text": {
        +      "type": "string"
        +    },
        +    "timestamp": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "message_id",
        +    "chat_id",
        +    "text",
        +    "timestamp",
        +    "account_id"
        +  ],
        +  "type": "object"
        +}
    • Addedfind_contact
    • Removedforward_message
    • Removedget_contact
    • Changedget_group_info3 fields changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
      • changedInput schema / properties / group_id / description
        Previous value: -"Group chat id (\"<id>@g.us\")"New value: +"<id>@g.us"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "account_id": {
        +      "type": "string"
        +    },
        +    "announcement_only": {
        +      "type": "boolean"
        +    },
        +    "chat_id": {
        +      "type": "string"
        +    },
        +    "community": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "is_community": {
        +          "type": "boolean"
        +        },
        +        "parent_group_id": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "is_community",
        +        "parent_group_id"
        +      ],
        +      "type": "object"
        +    },
        +    "created_at": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "description": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "disappearing_seconds": {
        +      "type": "number"
        +    },
        +    "i_am_admin": {
        +      "type": "boolean"
        +    },
        +    "info_locked": {
        +      "type": "boolean"
        +    },
        +    "invite_link": {
        +      "type": "string"
        +    },
        +    "join_approval": {
        +      "type": "boolean"
        +    },
        +    "member_add_mode": {
        +      "enum": [
        +        "admins",
        +        "all"
        +      ],
        +      "type": "string"
        +    },
        +    "name": {
        +      "type": "string"
        +    },
        +    "owner": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "participant_count": {
        +      "type": "number"
        +    },
        +    "participants": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "contact_id": {
        +            "type": "string"
        +          },
        +          "is_admin": {
        +            "type": "boolean"
        +          },
        +          "name": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "contact_id",
        +          "name",
        +          "is_admin"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "chat_id",
        +    "name",
        +    "description",
        +    "owner",
        +    "created_at",
        +    "participant_count",
        +    "participants",
        +    "announcement_only",
        +    "i_am_admin",
        +    "info_locked",
        +    "member_add_mode",
        +    "join_approval",
        +    "disappearing_seconds",
        +    "account_id"
        +  ],
        +  "type": "object"
        +}
    • Addedget_media
    • Changedget_message3 fields changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
      • removedInput schema / properties / message_id / description
        Removed value: -"Message id from read_messages / search_messages / get_message, e.g. \"false_4072...@s.whatsapp.net_3EB0...\""
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "account_id": {
        +      "type": "string"
        +    },
        +    "chat_id": {
        +      "type": "string"
        +    },
        +    "message_id": {
        +      "type": "string"
        +    },
        +    "text": {
        +      "type": "string"
        +    },
        +    "timestamp": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "message_id",
        +    "chat_id",
        +    "text",
        +    "timestamp",
        +    "account_id"
        +  ],
        +  "type": "object"
        +}
    • Removedget_recent_messages
    • Changedget_status1 field changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
    • Removedget_stories
    • Removedget_unanswered
    • Removedjoin_group
    • Changedlearn1 field changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
    • Changedlink_account2 fields changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
      • changedInput schema / properties / phone / description
        Previous value: -"International format, e.g. +15550100"New value: +"e.g. +15550100"
    • Removedlist_accounts
    • Changedlist_chats4 fields changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
      • changedInput schema / properties / filter / description
        Previous value: -"Which chats to list; \"all\" (default) excludes archived ones"New value: +"\"all\" leaves out archived"
      • removedInput schema / properties / limit / description
        Removed value: -"Maximum number of chats (1-100)"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "account_id": {
        +      "type": "string"
        +    },
        +    "chats": {
        +      "items": {
        +        "additionalProperties": true,
        +        "properties": {
        +          "chat_id": {
        +            "type": "string"
        +          },
        +          "last_message": {
        +            "anyOf": [
        +              {
        +                "additionalProperties": true,
        +                "properties": {
        +                  "private": {
        +                    "const": true,
        +                    "description": "Tagged #private: no words",
        +                    "type": "boolean"
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          },
        +          "name": {
        +            "type": "string"
        +          },
        +          "type": {
        +            "type": "string"
        +          },
        +          "unread_count": {
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "chat_id",
        +          "name",
        +          "type",
        +          "unread_count"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "count": {
        +      "type": "number"
        +    },
        +    "filter": {
        +      "type": "string"
        +    },
        +    "sync": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "filter",
        +    "count",
        +    "chats",
        +    "sync",
        +    "account_id"
        +  ],
        +  "type": "object"
        +}
    • Changedmanage_chat6 fields changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
      • removedInput schema / properties / action / description
        Removed value: -"What to do with the chat"
      • changedInput schema / properties / chat_id / description
        Previous value: -"Chat id as returned by another tool (\"<digits>@s.whatsapp.net\" or \"<id>@g.us\"), or a phone number in international format"New value: +"Chat id, or a phone number"
      • changedInput schema / properties / message_id / description
        Previous value: -"The message for pin_message, unpin_message, star_message and unstar_message; it must be in chat_id"New value: +"pin_message, star_message and their undo; in chat_id"
      • changedInput schema / properties / mute_hours / description
        Previous value: -"Hours to mute, default 8; only used by \"mute\""New value: +"mute: 8 by default"
      • changedInput schema / properties / pin_hours / description
        Previous value: -"How long pin_message keeps the message pinned: 24, 168 (default) or 720 hours"New value: +"pin_message: 168 by default"
    • Changedmanage_group13 fields changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
      • removedInput schema / properties / action / description
        Removed value: -"Group action to perform"
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "add",
        -  "remove",
        -  "promote",
        -  "demote",
        -  "leave",
        -  "set_subject",
        -  "set_description",
        -  "set_picture",
        -  "remove_picture",
        -  "get_invite_link",
        -  "revoke_invite_link",
        -  "list_join_requests",
        -  "approve_join_requests",
        -  "reject_join_requests",
        -  "set_announcement_only",
        -  "set_info_locked",
        -  "set_add_mode",
        -  "set_join_approval",
        -  "set_disappearing"
        -]New value: +[
        +  "create",
        +  "join",
        +  "add",
        +  "remove",
        +  "promote",
        +  "demote",
        +  "leave",
        +  "set_subject",
        +  "set_description",
        +  "set_picture",
        +  "remove_picture",
        +  "get_invite_link",
        +  "revoke_invite_link",
        +  "list_join_requests",
        +  "approve_join_requests",
        +  "reject_join_requests",
        +  "set_announcement_only",
        +  "set_info_locked",
        +  "set_add_mode",
        +  "set_join_approval",
        +  "set_disappearing"
        +]
      • addedInput schema / properties / confirm
        Added value: +{
        +  "default": false,
        +  "description": "join: true joins, after the user said yes to the preview",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / file_path / description
        Previous value: -"set_picture: absolute path of a local JPEG, PNG or WebP"New value: +"set_picture: local JPEG, PNG or WebP"
      • changedInput schema / properties / group_id / description
        Previous value: -"Group chat id (\"<id>@g.us\")"New value: +"\"<id>@g.us\"; every action but create and join"
      • addedInput schema / properties / invite
        Added value: +{
        +  "description": "join: a chat.whatsapp.com link or its code",
        +  "maxLength": 512,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / message_id
        Added value: +{
        +  "description": "join: an invite message instead",
        +  "minLength": 5,
        +  "type": "string"
        +}
      • changedInput schema / properties / participant_ids / description
        Previous value: -"Targets of add/remove/promote/demote/approve_join_requests/reject_join_requests"New value: +"create, add, remove, promote, demote, approve or reject"
      • changedInput schema / properties / url / description
        Previous value: -"set_picture: public http(s) URL to fetch and use as the photo"New value: +"set_picture: public image URL"
      • changedInput schema / properties / value / description
        Previous value: -"New subject or description; \"on\"/\"off\" for set_announcement_only, set_info_locked, set_join_approval; \"admins\"/\"all\" for set_add_mode; \"off\"/\"24h\"/\"7d\"/\"90d\" for set_disappearing"New value: +"The name (create, set_subject) or description; \"on\"/\"off\"; set_add_mode \"admins\"/\"all\"; set_disappearing \"off\"/\"24h\"/\"7d\"/\"90d\""
      • changedInput schema / required
        Previous value: -[
        -  "group_id",
        -  "action"
        -]New value: +[
        +  "action"
        +]
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "account_id": {
        +      "type": "string"
        +    },
        +    "action": {
        +      "type": "string"
        +    },
        +    "applied": {
        +      "type": "string"
        +    },
        +    "description": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "group_id": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "invite_link": {
        +      "type": "string"
        +    },
        +    "join_approval": {
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "join_requests": {
        +      "items": {
        +        "additionalProperties": true,
        +        "properties": {},
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "name": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "next": {
        +      "description": "join preview: the step after the user's yes",
        +      "type": "string"
        +    },
        +    "participant_count": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "participants": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "id": {
        +            "type": "string"
        +          },
        +          "reason": {
        +            "type": "string"
        +          },
        +          "status": {
        +            "enum": [
        +              "ok",
        +              "invite_needed",
        +              "failed"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "id",
        +          "status"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "profile_pic_url": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "status": {
        +      "description": "join: preview joins nothing",
        +      "enum": [
        +        "preview",
        +        "joined",
        +        "pending_approval"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "action",
        +    "group_id",
        +    "account_id"
        +  ],
        +  "type": "object"
        +}
    • Removedmark_handled
    • Changedreact_to_message4 fields changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
      • removedInput schema / properties / emoji / description
        Removed value: -"A single emoji such as \"👍\", or \"\" to remove your reaction"
      • removedInput schema / properties / message_id / description
        Removed value: -"Message id from read_messages / search_messages / get_message, e.g. \"false_4072...@s.whatsapp.net_3EB0...\""
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "account_id": {
        +      "type": "string"
        +    },
        +    "emoji": {
        +      "type": "string"
        +    },
        +    "message_id": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "message_id",
        +    "emoji",
        +    "account_id"
        +  ],
        +  "type": "object"
        +}
    • Changedread_messages8 fields changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
      • changedInput schema / properties / before / description
        Previous value: -"Return the messages immediately older than this message_id"New value: +"The oldest message_id you have"
      • changedInput schema / properties / chat_id / description
        Previous value: -"Chat id as returned by another tool (\"<digits>@s.whatsapp.net\" or \"<id>@g.us\"), or a phone number in international format"New value: +"Chat id from another tool, a phone number, or \"status\" for stories"
      • addedInput schema / properties / hours
        Added value: +{
        +  "description": "\"status\" only: how far back, 24 by default",
        +  "maximum": 24,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • changedInput schema / properties / include_previews / description
        Previous value: -"Attach a small JPEG of each photo, newest first, up to 12 per call, so you can see what was sent: the preview WhatsApp shipped when there is one, otherwise the photo is downloaded once and shrunk on the machine running wazap"New value: +"Attach a small image of each photo, up to 12"
      • removedInput schema / properties / limit / description
        Removed value: -"Maximum number of messages (1-200)"
      • changedInput schema / properties / types / description
        Previous value: -"Keep only these message types; omit for every type. The limit counts matching messages, so [\"call\"] returns that many calls, not that many messages of which some are calls."New value: +"Only these types; limit counts them, so [\"call\"] gives that many calls"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "account_id": {
        +      "type": "string"
        +    },
        +    "chat_id": {
        +      "type": "string"
        +    },
        +    "count": {
        +      "type": "number"
        +    },
        +    "hours": {
        +      "type": "number"
        +    },
        +    "messages": {
        +      "items": {
        +        "additionalProperties": true,
        +        "properties": {
        +          "chat_id": {
        +            "type": "string"
        +          },
        +          "message_id": {
        +            "type": "string"
        +          },
        +          "private": {
        +            "const": true,
        +            "description": "Tagged #private: no words",
        +            "type": "boolean"
        +          },
        +          "text": {
        +            "type": "string"
        +          },
        +          "timestamp": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "message_id",
        +          "chat_id",
        +          "text",
        +          "timestamp"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "notes": {
        +      "description": "Caveats to act on or tell the user",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "older": {
        +      "additionalProperties": false,
        +      "description": "before ran past the local history: the phone was asked, and sent this many",
        +      "properties": {
        +        "asked_phone": {
        +          "const": true,
        +          "type": "boolean"
        +        },
        +        "received": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "asked_phone",
        +        "received"
        +      ],
        +      "type": "object"
        +    },
        +    "omitted": {
        +      "description": "Older stories left out by limit",
        +      "type": "number"
        +    },
        +    "preview_count": {
        +      "type": "number"
        +    },
        +    "sync": {
        +      "type": "string"
        +    },
        +    "types": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "unconfirmed_sends": {
        +      "description": "Sends WhatsApp has not echoed yet: outcome unknown, not failed",
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "draft_id": {
        +            "type": "string"
        +          },
        +          "handed_at": {
        +            "type": "string"
        +          },
        +          "state": {
        +            "const": "unknown",
        +            "type": "string"
        +          },
        +          "text": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "draft_id",
        +          "text",
        +          "handed_at",
        +          "state"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "chat_id",
        +    "count",
        +    "preview_count",
        +    "messages",
        +    "sync",
        +    "account_id"
        +  ],
        +  "type": "object"
        +}
    • Removedrecall
    • Addedremember
    • Removedremove_contact
    • Removedsave_contact
    • Addedsearch
    • Removedsearch_contacts
    • Removedsearch_messages
    • Removedsend_location
    • Removedsend_media
    • Changedsend_message15 fields changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
      • addedInput schema / properties / address
        Added value: +{
        +  "description": "Location: shown under the name",
        +  "maxLength": 500,
        +  "type": "string"
        +}
      • addedInput schema / properties / as
        Added value: +{
        +  "description": "Media: a plain document, a voice note, a looping GIF",
        +  "enum": [
        +    "document",
        +    "voice",
        +    "gif"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / chat_id / description
        Previous value: -"Chat id as returned by another tool (\"<digits>@s.whatsapp.net\" or \"<id>@g.us\"), or a phone number in international format"New value: +"Chat id, or a phone number"
      • addedInput schema / properties / file_path
        Added value: +{
        +  "description": "Media: absolute path on the machine running wazap",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / forward
        Added value: +{
        +  "$ref": "#/properties/reply_to",
        +  "description": "Forward this message; text \"\""
        +}
      • addedInput schema / properties / latitude
        Added value: +{
        +  "maximum": 90,
        +  "minimum": -90,
        +  "type": "number"
        +}
      • addedInput schema / properties / longitude
        Added value: +{
        +  "maximum": 180,
        +  "minimum": -180,
        +  "type": "number"
        +}
      • changedInput schema / properties / mention_ids / description
        Previous value: -"Chat ids to @-mention; write @<number> in the text for each, or wazap adds it at the end"New value: +"Chat ids to @-mention; write @<number> in text for each"
      • addedInput schema / properties / multi_select
        Added value: +{
        +  "description": "Poll: several answers allowed",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / options
        Added value: +{
        +  "description": "Poll answers",
        +  "items": {
        +    "maxLength": 100,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 12,
        +  "minItems": 2,
        +  "type": "array"
        +}
      • removedInput schema / properties / reply_to / description
        Removed value: -"Quote-reply to this message"
      • changedInput schema / properties / text / description
        Previous value: -"The message text"New value: +"The message, or the caption, poll question or place name; \"\" for a forward, a voice note or audio"
      • removedInput schema / properties / text / minLength
        Removed value: -1
      • addedInput schema / properties / url
        Added value: +{
        +  "description": "Media: public http(s) URL",
        +  "format": "uri",
        +  "type": "string"
        +}
    • Removedsend_poll
    • Removedset_contact_note
    • Removedset_profile_picture
    • Removedsync_contacts
    • Removedtranscribe_audio
    • Removedupdate_contact_details
    • Changedwait_for_messages6 fields changed
      • changedInput schema / properties / account_id / description
        Previous value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
      • removedInput schema / properties / addressed_to_me / description
        Removed value: -"Only direct messages, @-mentions of the user and replies to the user's messages"
      • changedInput schema / properties / chat_id / description
        Previous value: -"Only messages in this chat"New value: +"Chat id, or a phone number"
      • changedInput schema / properties / cursor / description
        Previous value: -"The cursor returned by the previous call"New value: +"From the previous call"
      • removedInput schema / properties / timeout_seconds / description
        Removed value: -"How long to wait (1-55 s)"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "account_id": {
        +      "type": "string"
        +    },
        +    "count": {
        +      "type": "number"
        +    },
        +    "cursor": {
        +      "description": "Pass to the next call",
        +      "type": "string"
        +    },
        +    "cursor_reset": {
        +      "description": "The cursor was from another run; the wait started now",
        +      "type": "boolean"
        +    },
        +    "messages": {
        +      "items": {
        +        "additionalProperties": true,
        +        "properties": {
        +          "chat_id": {
        +            "type": "string"
        +          },
        +          "message_id": {
        +            "type": "string"
        +          },
        +          "private": {
        +            "const": true,
        +            "description": "Tagged #private: no words",
        +            "type": "boolean"
        +          },
        +          "text": {
        +            "type": "string"
        +          },
        +          "timestamp": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "message_id",
        +          "chat_id",
        +          "text",
        +          "timestamp"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "timed_out": {
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "count",
        +    "messages",
        +    "cursor",
        +    "timed_out",
        +    "cursor_reset",
        +    "account_id"
        +  ],
        +  "type": "object"
        +}
  2. 13 tool updatesv0.21.0
    • Changeddelete_message3 fields changed
      • removedInput schema / properties / for_everyone / default
        Removed value: -false
      • changedInput schema / properties / for_everyone / description
        Previous value: -"Retract for all participants (WhatsApp supports no other kind of delete here)"New value: +"Required. true retracts it for everyone in the chat; false deletes it for the linked account only"
      • changedInput schema / required
        Previous value: -[
        -  "message_id"
        -]New value: +[
        +  "message_id",
        +  "for_everyone"
        +]
    • Changedget_recent_messages1 field changed
      • changedInput schema / properties / types / items / enum
        Previous value: -[
        -  "text",
        -  "image",
        -  "video",
        -  "audio",
        -  "voice",
        -  "document",
        -  "sticker",
        -  "location",
        -  "contact",
        -  "poll",
        -  "reaction",
        -  "deleted",
        -  "view_once",
        -  "call",
        -  "system",
        -  "unknown"
        -]New value: +[
        +  "text",
        +  "image",
        +  "video",
        +  "audio",
        +  "voice",
        +  "document",
        +  "sticker",
        +  "location",
        +  "contact",
        +  "poll",
        +  "reaction",
        +  "deleted",
        +  "view_once",
        +  "call",
        +  "event",
        +  "invite",
        +  "system",
        +  "unknown"
        +]
    • Addedjoin_group
    • Changedmanage_chat3 fields changed
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "archive",
        -  "unarchive",
        -  "pin",
        -  "unpin",
        -  "mute",
        -  "unmute",
        -  "mark_read",
        -  "mark_unread"
        -]New value: +[
        +  "archive",
        +  "unarchive",
        +  "pin",
        +  "unpin",
        +  "mute",
        +  "unmute",
        +  "mark_read",
        +  "mark_unread",
        +  "pin_message",
        +  "unpin_message",
        +  "star_message",
        +  "unstar_message",
        +  "clear",
        +  "delete",
        +  "block",
        +  "unblock"
        +]
      • addedInput schema / properties / message_id
        Added value: +{
        +  "description": "The message for pin_message, unpin_message, star_message and unstar_message; it must be in chat_id",
        +  "minLength": 5,
        +  "type": "string"
        +}
      • addedInput schema / properties / pin_hours
        Added value: +{
        +  "description": "How long pin_message keeps the message pinned: 24, 168 (default) or 720 hours",
        +  "enum": [
        +    24,
        +    168,
        +    720
        +  ],
        +  "type": "number"
        +}
    • Changedmanage_group5 fields changed
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "add",
        -  "remove",
        -  "promote",
        -  "demote",
        -  "leave",
        -  "set_subject",
        -  "set_description",
        -  "get_invite_link",
        -  "revoke_invite_link"
        -]New value: +[
        +  "add",
        +  "remove",
        +  "promote",
        +  "demote",
        +  "leave",
        +  "set_subject",
        +  "set_description",
        +  "set_picture",
        +  "remove_picture",
        +  "get_invite_link",
        +  "revoke_invite_link",
        +  "list_join_requests",
        +  "approve_join_requests",
        +  "reject_join_requests",
        +  "set_announcement_only",
        +  "set_info_locked",
        +  "set_add_mode",
        +  "set_join_approval",
        +  "set_disappearing"
        +]
      • addedInput schema / properties / file_path
        Added value: +{
        +  "description": "set_picture: absolute path of a local JPEG, PNG or WebP",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedInput schema / properties / participant_ids / description
        Previous value: -"Targets of add/remove/promote/demote"New value: +"Targets of add/remove/promote/demote/approve_join_requests/reject_join_requests"
      • addedInput schema / properties / url
        Added value: +{
        +  "description": "set_picture: public http(s) URL to fetch and use as the photo",
        +  "format": "uri",
        +  "type": "string"
        +}
      • changedInput schema / properties / value / description
        Previous value: -"New subject or description"New value: +"New subject or description; \"on\"/\"off\" for set_announcement_only, set_info_locked, set_join_approval; \"admins\"/\"all\" for set_add_mode; \"off\"/\"24h\"/\"7d\"/\"90d\" for set_disappearing"
    • Changedread_messages1 field changed
      • changedInput schema / properties / types / items / enum
        Previous value: -[
        -  "text",
        -  "image",
        -  "video",
        -  "audio",
        -  "voice",
        -  "document",
        -  "sticker",
        -  "location",
        -  "contact",
        -  "poll",
        -  "reaction",
        -  "deleted",
        -  "view_once",
        -  "call",
        -  "system",
        -  "unknown"
        -]New value: +[
        +  "text",
        +  "image",
        +  "video",
        +  "audio",
        +  "voice",
        +  "document",
        +  "sticker",
        +  "location",
        +  "contact",
        +  "poll",
        +  "reaction",
        +  "deleted",
        +  "view_once",
        +  "call",
        +  "event",
        +  "invite",
        +  "system",
        +  "unknown"
        +]
    • Addedrecall
    • Addedremove_contact
    • Addedsave_contact
    • Changedsearch_contacts3 fields changed
      • changedInput schema / properties / query / description
        Previous value: -"Name fragment or phone number (at least 2 characters)"New value: +"Name fragment, phone number, or tag/detail text (at least 2 characters). Omit with tag to list everyone carrying it."
      • addedInput schema / properties / tag
        Added value: +{
        +  "description": "Only contacts filed under this tag (\"client\"); \"#\" optional",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "query"
        -]
    • Changedsearch_messages1 field changed
      • changedInput schema / properties / from / description
        Previous value: -"Only messages this person sent: \"me\", a contact id or a phone number"New value: +"Only messages this person sent: \"me\", a phone number, a contact/chat id, or a name that resolves to exactly one person (the error names the candidates when it does not)"
    • Changedsend_message1 field changed
      • changedInput schema / properties / mention_ids / description
        Previous value: -"Chat ids to @-mention; include their names in the text yourself"New value: +"Chat ids to @-mention; write @<number> in the text for each, or wazap adds it at the end"
    • Addedupdate_contact_details
  3. 33 tool updatesv0.15.0
    • Addedconfirm_send
    • Changedcreate_group1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changeddelete_message1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changeddownload_media1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changededit_message1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changedforward_message1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changedget_contact1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changedget_group_info1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changedget_message1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changedget_recent_messages3 fields changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / compact
        Added value: +{
        +  "default": false,
        +  "description": "Leave out media without a caption and messages with no words in them, fold what one person sent in a row into one line, and say per chat what was left out. About half the size; use it for a routine catch-up",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / include_previews
        Added value: +{
        +  "default": false,
        +  "description": "Attach a small JPEG of each photo, newest first, up to 12 per call, so you can see what was sent: the preview WhatsApp shipped when there is one, otherwise the photo is downloaded once and shrunk on the machine running wazap",
        +  "type": "boolean"
        +}
    • Changedget_status2 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Addedget_stories
    • Addedget_unanswered
    • Changedlearn2 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Addedlink_account
    • Addedlist_accounts
    • Changedlist_chats1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changedmanage_chat1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changedmanage_group1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Addedmark_handled
    • Changedreact_to_message1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changedread_messages2 fields changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / include_previews
        Added value: +{
        +  "default": false,
        +  "description": "Attach a small JPEG of each photo, newest first, up to 12 per call, so you can see what was sent: the preview WhatsApp shipped when there is one, otherwise the photo is downloaded once and shrunk on the machine running wazap",
        +  "type": "boolean"
        +}
    • Changedsearch_contacts1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changedsearch_messages4 fields changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / from
        Added value: +{
        +  "description": "Only messages this person sent: \"me\", a contact id or a phone number",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / since
        Added value: +{
        +  "description": "Only messages from this moment on: a date (\"2026-09-01\") or an ISO timestamp",
        +  "minLength": 4,
        +  "type": "string"
        +}
      • addedInput schema / properties / until
        Added value: +{
        +  "description": "Only messages up to this moment: a date or an ISO timestamp",
        +  "minLength": 4,
        +  "type": "string"
        +}
    • Changedsend_location1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changedsend_media2 fields changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / as_gif
        Added value: +{
        +  "default": false,
        +  "description": "Send a .gif or an mp4 as a looping GIF, the way WhatsApp plays them",
        +  "type": "boolean"
        +}
    • Changedsend_message1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changedsend_poll1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Addedset_contact_note
    • Addedset_profile_picture
    • Changedsync_contacts2 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changedtranscribe_audio1 field changed
      • addedInput schema / properties / account_id
        Added value: +{
        +  "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.",
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Addedwait_for_messages
  4. 4 tool updatesv0.10.0
    • Changedget_recent_messages2 fields changed
      • addedInput schema / properties / include_system
        Added value: +{
        +  "default": false,
        +  "description": "Include WhatsApp's own system notices, which are excluded from the bodies and the counts by default",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / types
        Added value: +{
        +  "description": "Keep only these message types; omit for every type. The limit counts matching messages, so [\"call\"] returns that many calls, not that many messages of which some are calls.",
        +  "items": {
        +    "enum": [
        +      "text",
        +      "image",
        +      "video",
        +      "audio",
        +      "voice",
        +      "document",
        +      "sticker",
        +      "location",
        +      "contact",
        +      "poll",
        +      "reaction",
        +      "deleted",
        +      "view_once",
        +      "call",
        +      "system",
        +      "unknown"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
    • Changedread_messages1 field changed
      • addedInput schema / properties / types
        Added value: +{
        +  "description": "Keep only these message types; omit for every type. The limit counts matching messages, so [\"call\"] returns that many calls, not that many messages of which some are calls.",
        +  "items": {
        +    "enum": [
        +      "text",
        +      "image",
        +      "video",
        +      "audio",
        +      "voice",
        +      "document",
        +      "sticker",
        +      "location",
        +      "contact",
        +      "poll",
        +      "reaction",
        +      "deleted",
        +      "view_once",
        +      "call",
        +      "system",
        +      "unknown"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
    • Addedsync_contacts
    • Addedtranscribe_audio
  5. 22 tool updatesv0.9.3
    • First observedcreate_group
    • First observeddelete_message
    • First observeddownload_media
    • First observededit_message
    • First observedforward_message
    • First observedget_contact
    • First observedget_group_info
    • First observedget_message
    • First observedget_recent_messages
    • First observedget_status
    • First observedlearn
    • First observedlist_chats
    • First observedmanage_chat
    • First observedmanage_group
    • First observedreact_to_message
    • First observedread_messages
    • First observedsearch_contacts
    • First observedsearch_messages
    • First observedsend_location
    • First observedsend_media
    • First observedsend_message
    • First observedsend_poll

TDQS

A3.9/5.0

Scored across 20 tools

Disambiguation4/5

Most tools have clearly distinct purposes (e.g., send_message vs. confirm_send vs. edit_message vs. delete_message are well-separated by lifecycle stage). However, manage_chat and manage_group both handle 'manage' actions across different resources, and get_message vs. read_messages could cause minor confusion despite different scopes.

Naming Consistency4/5

The naming is predominantly verb_noun (get_status, list_chats, read_messages, send_message, edit_message, delete_message, find_contact, get_group_info, get_media). Minor deviations: 'learn', 'catch_up', 'remember', 'wait_for_messages' are less pattern-consistent but still readable and purposeful.

Tool Count4/5

20 tools is on the higher end but justified for a WhatsApp integration covering accounts, chats, groups, messages, media, contacts, and search. Each tool addresses a distinct operation, though a few could potentially be consolidated (e.g., manage_chat and manage_group are broad).

Completeness5/5

The tool surface covers the full messaging lifecycle: linking accounts, listing/reading/searching messages, drafting/sending/editing/reacting/deleting, chat and group management, contact resolution, media retrieval, and catch-up. The inclusion of learn, get_status, and wait_for_messages fills operational gaps that agents would otherwise hit.

Maintenance

ActivityActive
ResponsivenessUnresponsive

Related MCP Connectors

  • WhatsMCP connects Claude and other MCP-compatible AI agents directly to WhatsApp. Send and receive text, images, documents, and voice notes; manage groups (create, add/remove members, promote admins); look up contacts and profiles; follow channels; and read call and message history — all through a standard MCP interface. For voice use cases, WhatsMCP offers SIP-based calling plans (inbound-only, or full inbound/outbound) so AI voice agents can answer and place WhatsApp calls, plus low-latency WebSocket integrations with voice agent providers like ElevenLabs. Multiple WhatsApp accounts can be paired and managed per workspace, with webhook support for real-time inbound message delivery to your own infrastructure.

  • Drive WhatsApp from any MCP client: pair devices, send text and media, manage contacts and groups.

  • Your own WhatsApp as an MCP server: read, search and send from any MCP client.

  • MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    WhatsApp MCP server that exposes messaging, groups, contacts, and profile management as tools and resources for AI agents, supporting Baileys and Meta Cloud API.
    23
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    A self-hosted WhatsApp bridge that exposes a stdio MCP server with ~20 tools for reading conversations, sending messages, managing groups, contacts, and aliases, enabling AI agents to operate WhatsApp directly.
    3
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server that connects AI agents to WhatsApp using the multi-device API, enabling messaging, group management, and more as a regular user.
    10 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A native MCP server for SocialMate that gives your AI a WhatsApp, enabling it to send and read messages, manage contacts and groups, and more through 44 tools.
    14 npm
    1
    MIT