Skip to main content
Glama
razvangirgiz

wazap-mcp

by razvangirgiz
╭───────────────╮
│        ▄██▀   │   ██╗    ██╗ █████╗ ███████╗ █████╗ ██████╗
│      ▄██▀     │   ██║    ██║██╔══██╗╚══███╔╝██╔══██╗██╔══██╗
│    ▄███████▀  │   ██║ █╗ ██║███████║  ███╔╝ ███████║██████╔╝
│       ▄██▀    │   ██║███╗██║██╔══██║ ███╔╝  ██╔══██║██╔═══╝
│     ▄█▀       │   ╚███╔███╔╝██║  ██║███████╗██║  ██║██║
╰─╮╭────────────╯    ╚══╝╚══╝ ╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚═╝
  ╰╯                WhatsApp for your AI agent.

npm License: MIT M8ven Score

wazap is an MCP server for your own WhatsApp account. It links as a device, the way WhatsApp Web does, keeps what it sees on your machine, and gives any MCP client — Claude, ChatGPT, Gemini, Cursor, Codex — 23 tools over your chats, messages, media, contacts and groups.

You stop opening WhatsApp to find things and ask instead:

  • "What did I miss on WhatsApp today?" — one answer across every linked account: who is waiting on you, mentions, missed calls, busy 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 notes come back as text.

  • "Tell Ana I'll be twenty minutes late." — you see the recipient and the exact words first. Nothing leaves until you say yes.

No browser, no business account, no third-party service. There is no wazap cloud: it runs where you run it.

Get started

You need Node.js 22.16+ on the 22 line, or 24+, and a phone with WhatsApp.

npx wazap-mcp setup

setup links your account, finds the MCP clients installed on this machine (Claude Code, Claude Desktop, Cursor, Codex, Gemini CLI), writes their config, installs the five skills where the client reads them, and tells you what to restart. Then ask your assistant: "what did I miss on WhatsApp today?"

Rather let your agent do it? Paste this into it:

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

npx wazap-mcp on its own, in a terminal, starts nothing: it prints where you stand and the next command. When something is off, npx wazap-mcp status is the first thing to run; it prints a fix next to anything broken.

Per client

Client

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

Cursor

the badge below, then npx wazap-mcp skills install cursor

Codex CLI

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

Gemini CLI

npx wazap-mcp connect gemini

claude.ai, ChatGPT, other hosted agents

a URL they sign in to with OAuth: see Remote access

Anything else

command npx -y wazap-mcp, transport stdio

Install in Cursor

The hand-written entry, for any client that takes the usual JSON:

{
  "mcpServers": {
    "whatsapp": { "command": "npx", "args": ["-y", "wazap-mcp"] }
  }
}

Every step setup takes, each file connect writes, and upgrading are in docs/install.md.

Related MCP server: wa-bridge

Linking your account

Linking is a one-time step. setup does it for you; on its own it is:

npx wazap-mcp login                      # QR code: Settings → Linked devices → Link a device
npx wazap-mcp login --phone +15550100    # pairing code instead, no camera needed

With --phone, wazap prints an 8-character code. On the phone, go to WhatsApp → Settings → Linked devices → Link a device → Link with phone number instead and type it in. The pairing code works over SSH and on a headless server, where a QR is impractical.

An assistant can link the account itself, too: the link_account tool returns the same code, so a Claude Desktop user never needs a terminal.

Several WhatsApp accounts can live in one wazap (wazap account add <id>, then wazap login --account <id>); see docs/accounts.md.

The 23 tools

What every argument means, and every error code, is in docs/tools.md. The assistant gets all of it by calling learn.

Tool

Kind

What it does

learn

read

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

get_status

read

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

link_account

read

Link 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

One 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, reactions and who left them, poll votes, delivery and read receipts.

find_contact

read

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

list_contacts

read

The phone's address book a page at a time: saved name, number, when you last talked.

get_group_info

read

Participants, admins, group settings, the invite link for an admin.

get_media

read

A voice note as its transcript, a photo as an image, any file saved to disk; served from the copy kept on arrival first.

wait_for_messages

read

Block up to 55 s until a message arrives, with a cursor so nothing is missed between calls.

remember

local

A note, tags or details about a person, kept on this machine. Nothing changes on WhatsApp.

send_message

write

Draft a message, media, poll, location or forward — and send nothing. send_at drafts it for a later time.

confirm_send

write

Send that draft, once, after the user has seen the preview and said yes; a draft for later is scheduled.

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

Delete for everyone (your own message, or anyone's in a group you admin), or only on this account.

manage_chat

write

Preview archive, pin, mute, star, clear, delete, block and undo actions; confirm the preview to apply once. mark_read remains direct.

manage_group

write

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

scheduled_messages

write

List the scheduled messages (sent, missed, failed too) or cancel one before it goes.

reminder

local

"Remind me if Ana has not answered in 2 days": set, list or cancel; posted to your webhook when due.

Scheduled messages and reminders. send_message with send_at ("tomorrow at 9" as 2026-10-12T09:00 in Europe/Bucharest) drafts a message for later; the user's yes to that preview, time included, schedules it, and every send check runs again when it goes. One wazap could not send within 15 minutes of its time is reported as missed, never sent late. reminder keeps "remind me if Ana has not answered in 2 days" and posts it to your webhook when due. Both survive restarts; see Scheduling a message and Reminders.

Two features are off by default and can run entirely on your machine: voice transcription with whisper.cpp (docs/voice.md) and semantic recall, so search matches meaning and not only words (docs/recall.md). Turn them on with wazap config transcribe local and wazap config recall local.

Skills

Tools say what is possible; the five Agent Skills in skills/ say how to do the job well.

Skill

What the agent does

whatsapp-inbox

Triage: needs you / FYI / noise, plus replies you forgot. Read-only.

whatsapp-recall

Find an address, an invoice, a photo, a thing someone said. Read-only.

whatsapp-groups

Catch up on a busy group: decisions, dates, what is asked of you. Read-only.

whatsapp-send

Find who you mean, draft in the chat's own tone, show it, send on a yes.

wazap-setup

Diagnose, link or repair the connection.

setup installs them for Claude Code, Codex and Cursor (npx wazap-mcp skills install <harness> does it by hand). Every other client gets the same five as MCP prompts from the server, with nothing to install.

Transports

stdio is the default: the client starts npx -y wazap-mcp and talks to it over stdin/stdout. Nothing listens on the network.

HTTP (Streamable HTTP) is for a server that outlives the client, or one another machine reaches:

npx wazap-mcp serve --http                 # http://127.0.0.1:8766/mcp, health at /healthz

--host/--port (or WAZAP_HOST/WAZAP_PORT) move it. wazap refuses to bind anything but loopback without WAZAP_READ_TOKEN. Clients authenticate with a static bearer token (WAZAP_READ_TOKEN, plus WAZAP_WRITE_TOKEN for the write tools) or with OAuth 2.1, which wazap serves itself. Details in docs/self-host.md.

Remote access

Two commands keep wazap running and reachable from hosted agents:

npx wazap-mcp service install   # a launchd agent (macOS) or systemd user unit (Linux)
npx wazap-mcp expose            # a public https URL through Tailscale Funnel or Cloudflare Tunnel

expose prints the URL and a consent password. Give the agent only the URL; it registers itself, and the consent page asks you for the password and whether that agent may only read or also send. See Keep it running.

The service recovers by itself: a dropped link is retried with backoff, a watchdog replaces a socket that went dead across a sleep or stopped answering, and when reconnecting keeps failing wazap exits so launchd or systemd starts it fresh. The linked session is never deleted for any of that; only WhatsApp unlinking the device needs a new link. Set WAZAP_WEBHOOK_EVENTS to include alert to be told when the link has been down for 5 minutes, when it is back, and when it needs linking again (Link alerts); get_status shows the same under link.

Deployment

On a server of your own, the session never leaves it. With Docker (images for amd64 and arm64 at ghcr.io/razvangirgiz/wazap):

mkdir wazap && cd wazap
curl -fsSLO https://raw.githubusercontent.com/razvangirgiz/wazap/main/docker-compose.yml
printf 'WAZAP_READ_TOKEN=%s\nWAZAP_WRITE_TOKEN=%s\n' $(openssl rand -hex 32) $(openssl rand -hex 32) > .env
docker compose run --rm wazap login --phone +15550100   # once; the session lands in the volume
docker compose up -d
curl -s http://127.0.0.1:8766/healthz

The container publishes port 8766 on loopback only; put TLS in front (deploy/Caddyfile is two lines). A systemd unit is in deploy/wazap.service. Both setups, reverse-proxy trust and the OAuth server are in docs/self-host.md. Calling wazap from your own product, and receiving signed webhooks for incoming messages, is in docs/api-and-webhooks.md.

Configuration

Every setting is optional. They are environment variables, read from the process or from ~/.wazap/.env (a real environment variable wins, a flag wins over both). You rarely edit them by hand: wazap config shows the effective settings and changes one.

Setting

Default

What it does

WAZAP_DATA_DIR

~/.wazap

Where credentials, databases and models live (--data-dir too).

WAZAP_READ_ONLY

unset

1 does not register the write tools at all. wazap config writes on|off.

WAZAP_PERSIST_HISTORY

1

0 keeps no messages on disk across restarts.

WAZAP_HOST / WAZAP_PORT

127.0.0.1 / 8766

Where serve --http listens.

WAZAP_READ_TOKEN / WAZAP_WRITE_TOKEN

unset

Static bearer tokens for HTTP; only the write token gets the write tools.

WAZAP_PUBLIC_URL / WAZAP_OAUTH_PASSWORD

unset

Both together turn on OAuth for hosted agents. wazap expose sets them.

WAZAP_TRANSCRIBE

off

local (whisper.cpp) or openai (an OpenAI-compatible API).

WAZAP_RECALL

off

local turns on semantic search with a local embedding model.

WAZAP_WEBHOOK

off

on posts incoming messages to WAZAP_WEBHOOK_URL, signed with WAZAP_WEBHOOK_SECRET.

WAZAP_MEDIA_KEEP

unmuted

Which chats' media is downloaded on arrival and kept, so get_media outlives WhatsApp's copy: unmuted, all, chats or off. Limits: WAZAP_MEDIA_KEEP_MAX_MB, WAZAP_MEDIA_KEEP_QUOTA_MB, WAZAP_MEDIA_KEEP_DAYS.

The full list, including the webhook filters, kept-media limits, retention and proxy trust, is in docs/settings.md; .env.example is the same list as a commented file.

Security and privacy

  • Nothing is sent without a 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 proof of consent: an agent can call both tools unless your client makes you approve the second one.

  • Read-only is a real switch. With WAZAP_READ_ONLY=1, --read-only or wazap config writes off, the write tools are not registered, so the assistant cannot message anyone even by mistake. The Claude Desktop bundle ships with read-only ticked.

  • Recipients can be pinned. wazap config send allow +15550100,… limits an account to a list, deny refuses the ones named; both are checked at draft and again at send (docs/send-rules.md).

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

  • Your data stays on your machine. Credentials, messages, media and notes live in ~/.wazap (0700, credential files 0600). No account, no telemetry. What leaves the machine: WhatsApp traffic; the npm registry, for the version check; Hugging Face, when you download a transcription or embedding model; a transcription API, only if you chose openai; your own webhook, if you set one (docs/data.md).

  • Some people can be kept out. Tag a contact #private and their words stay out of everything the assistant did not ask about them by name, and out of the webhook. #no-catchup keeps their chat out of catch_up.

  • What it does not do. No bulk send, no scheduler, no campaigns. It never marks anything read on its own, and sends text without link previews, so nothing fetches the pages you link.

Threat model, findings and the limits of each of these: docs/security-audit.md.

Known limitations

  • The protocol is unofficial. wazap is built on Baileys, a reverse-engineered implementation of WhatsApp's multi-device protocol. It is not the WhatsApp Business API and Meta does not support it. A protocol change can break wazap until Baileys catches up, and an account that sends in bulk or to people who did not ask can be restricted or banned. The safeguards above reduce that risk; they do not remove it, and the risk is yours.

  • Model behaviour is measured on Claude only. The evaluation in eval/ (58 cases, each run three times) has been run on Claude. Other clients get the same tools and the same server-side guards, but nobody has measured how their models use them. The manual protocol for ChatGPT is eval/chatgpt-protocol.md.

  • History is what the phone syncs to a linked device, not your whole archive. read_messages with before asks the phone for more, within what WhatsApp still keeps.

  • Old media expires. WhatsApp drops old attachments from its servers; get_media then returns MEDIA_UNAVAILABLE, unless wazap kept a copy when it arrived. By default it keeps the photos, voice notes, audio and documents of unmuted chats, up to 16 MB each, 1 GB in all and 90 days, while wazap serve runs; media that arrived and expired while nothing was keeping it cannot be brought back.

  • Names come from the phone's address book, which WhatsApp only sends to a fresh connection. If contacts read as numbers (contacts_named: 0 in get_status), wazap contacts resync asks again while no server runs.

  • @lid ids. Newer accounts are addressed by a privacy id; wazap maps it back to a number when it has learned the mapping.

  • Calls are WhatsApp calls only, and a call that starts and ends while wazap is stopped may be missing. Cellular calls are never visible.

  • The phone must stay reachable. A linked device stops receiving once the phone has been offline too long; get_status says so.

What the 1.x line promises not to break is in docs/stability.md.

Documentation

docs/install.md

setup step by step, each client, the background service, expose, upgrading, skills

docs/tools.md

The 23 tools in full, the workflows, every error code

docs/accounts.md

Several WhatsApp accounts, several MCP clients on one server

docs/voice.md

Voice notes as text: whisper.cpp locally, or an OpenAI-compatible API

docs/recall.md

Semantic search with a local embedding model

docs/data.md

The data directory, wazap backup, retention, deleted and disappearing messages

docs/send-rules.md

Read-only mode, per-account send rules, rate limits

docs/self-host.md

HTTP mode, systemd, Docker, tunnels, proxy trust, OAuth

docs/api-and-webhooks.md

Static tokens in, signed webhook events out

docs/settings.md

Every WAZAP_* setting and its default

docs/security-audit.md

The security audit

docs/stability.md

What 1.0 promises to keep stable

CHANGELOG.md

Release by release

Contributing

git clone https://github.com/razvangirgiz/wazap && cd wazap
npm ci
npm run check                  # lint, typecheck, then build and test
node test/smoke-stdio.mjs      # drives the built binary over MCP stdio
npm run dev -- status          # run from source with tsx

The tests need no WhatsApp account. CLAUDE.md is the contributor's map: layout, the rules that must never break, and the release procedure. Issues and pull requests are welcome at github.com/razvangirgiz/wazap.

License

MIT © Răzvan Girgiz

Available Tools

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

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_idNo
budget_tokensNoAnswer length in tokens

Output 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.7/5.0
Behavior4/5

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

Annotations declare readOnlyHint=true and idempotentHint=false, and the description explains the non-obvious reason: 'The mark moves first', so a repeat call is not idempotent and a swallowed answer requires since: "previous". That is real side-effect disclosure the annotations cannot convey.

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?

Every clause carries information and the scope comes first, but the telegraphic fragments ('The mark moves first', 'more.cursor: the rest', 'a lost answer is since: "previous"') force the reader to reconstruct the grammar, which costs clarity for very little length saved.

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 an output schema present, return values need not be explained, and the description covers the remaining gaps: breadth across accounts, the token budget, the mark/cursor/repeat interaction. Only the 'waiting' 14-day exception ('whatever the window') is stated so tersely that its interaction with 'hours' stays murky.

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 83%, so the baseline is 3, and the description still adds meaning: 'hours ... never moves the mark', 'include' makes the mark stay, 'more.cursor: the rest', 'since: "previous" repeats that catch-up'. These are behaviors of the parameters, not restatements of their types.

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 opens with 'What the user missed, all accounts' and enumerates the sections returned (waiting, mentions, calls, people, groups, stories), so the resource and scope are clear. It never names a verb, but the digest nature distinguishes it well enough from search/read_messages siblings.

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?

'account_id narrows it to one account; get_status names them' gives a concrete routing rule to a sibling. However there is no statement of when to prefer this over read_messages or search, and the 'lost answer is since: "previous"' hint is recovery guidance rather than use-case guidance.

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.

NameRequiredDescriptionDefault
draft_idYesFrom send_message; one with send_at is scheduled, not sent
account_idNo

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the annotations, the description discloses key behavioral traits: it sends only the approved draft text to the approved recipient, sends once per draft, and must not be retried unasked after an unknown outcome. This adds meaningful safety and side-effect context for a high-stakes mutation tool.

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 short, front-loaded with the main send action, and every sentence carries operational value. The terse error-handling clauses are efficient rather than wasteful.

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 high-stakes send operation, it covers approval requirements, staleness, idempotency, and unknown-outcome recovery well. It does not describe successful return behavior or explain account_id, leaving a small completeness gap given there is no output 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?

The schema documents draft_id but leaves account_id undocumented, and the description does not explain account_id either. It reinforces draft uniqueness and approved-recipient semantics but only partially compensates for the 50% schema coverage gap.

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 ('Send a draft') and clarifies scope with 'this text, this recipient' and 'the only call that sends, once per draft.' It distinguishes the action from draft creation and from other sending-like siblings.

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?

It explicitly states when to send, what to do when the user's yes is about something else, what to do for expired/missing/stale drafts, and how to handle SEND_OUTCOME_UNKNOWN. These are concrete when/when-not and recovery instructions.

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.

NameRequiredDescriptionDefault
account_idNo
message_idYes
for_everyoneYes

Output Schema

NameRequiredDescription
account_idYes
message_idYes
for_everyoneYes

TDQS

A4.2/5.0
Behavior5/5

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

Beyond the destructiveHint/idempotentHint annotations, the description discloses the 2-day retraction window, the permission rule (own message or group admin), the limited blast radius of the local-delete mode, and the requirement to confirm with the user. These are exactly the facts an agent needs before performing an irreversible action.

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 critical safety instruction (confirm first) and the primary parameter are front-loaded, and no sentence is filler. The second half is a dense run-on clause chain, but every clause carries distinct information about scope and permissions.

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 destructive, open-world mutation with an output schema, the description covers confirmation, permission scope, time limits, and deletion breadth. Only the account_id parameter and multi-device/account selection semantics are left implicit.

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 0%, so the description must carry the parameter burden; it does so thoroughly for for_everyeen (both boolean values, their effects, and their eligibility constraints). message_id and account_id remain semantically unexplained beyond their names, which is a small residual gap.

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 opens with a specific verb and resource ("Delete a message") and immediately distinguishes the two deletion scopes via for_everyone. It is clearly separable from siblings like edit_message or send_message, though it does not explicitly name or contrast any sibling.

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 a concrete operational precondition ("confirm with the user first") and explains which mode applies when: for_everyone:true only within 2 days and only for one's own message or as a group admin; for_everyone:false for any message on the linked account's devices. Missing only an explicit comparison to alternative tools (e.g. edit_message) when a message should be changed rather than removed.

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.

NameRequiredDescriptionDefault
textYes
account_idNo
message_idYes

Output Schema

NameRequiredDescription
textYes
chat_idYes
timestampYes
account_idYes
message_idYes

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, so the description's job is lighter; it still adds the genuinely non-obvious 15-minute window and the ownership constraint. It doesn't say what happens on a rejected/timeout edit or whether the original text is recoverable, which would be the remaining useful detail for a destructive mutation.

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, zero filler, with the ownership scope and the time constraint front-loaded before the fallback advice.

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?

Output schema and annotations carry much of the load, and the time/ownership constraints are the key behavioral facts. However, for a destructive, open-world mutation with completely undocumented parameters, an agent is left guessing about account_id semantics and the failure modes of an expired or foreign message.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must carry parameter meaning. It conveys only that a message and its replacement text are involved, leaving account_id (optional, presumably the linked account selector) and the format/constraints of message_id undocumented anywhere.

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 precise verb+resource ('Replace the text of a message') and narrows scope to messages 'the linked account sent', which cleanly separates it from send_message, delete_message, and react_to_message in the sibling list.

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?

Gives an explicit eligibility window ('15 minutes after sending') and a fallback action ('send a correction instead'). It stops short of naming the sibling to use for the fallback, so the routing is implied rather than explicit.

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"), filed detail ("AP-123"), group, number or id means, before drafting. resolved: contact.chat_id, with number, note, tags, details and, when writing, context. ambiguous or not_found: ask the user; never guess. Several accounts: see fix. tag: its people.

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_idNo
include_contextNoRecent messages and the user's style, when resolved in a write session

Output 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

A3.8/5.0
Behavior4/5

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

Beyond the readOnly/idempotent/non-destructive annotations, it discloses the success shape (contact.chat_id plus number, note, tags, details, and context when writing) and the ambiguity/not_found policy. Gaps remain: 'see fix' is unexplained and it doesn't clarify account scoping behavior. Output schema covers the return payload, so this is solidly above baseline.

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?

It is short and front-loads the core resolution act, but the compression goes too far: sentence fragments and dangling references ('see fix') cost parseability. Space is saved at the expense of clarity rather than through it.

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, output-schema-backed lookup with strong annotations, the description covers resolution inputs, failure policy, write-session context, and the tag-listing mode. What's missing is a clear account_id/multi-account explanation and any note on limits, so it is good but not fully self-contained.

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 71%, so most parameters are already documented. The description reinforces tag listing ('tag: its people') and hints at qualifier disambiguation ('tells two apart' is in schema, not description), but it adds little on kind, limit, account_id, or include_context beyond what the schema states. Baseline 3 is appropriate.

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 specific job: resolve whatever the user said (name, nickname, relationship, filed detail, group, number, id) into a contact before drafting. It distinguishes itself from plain listing by framing this as 'who the user means', but the phrasing is telegraphic and it never names the obvious sibling (list_contacts) it replaces.

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 real usage context — call it 'before drafting', and on 'ambiguous or not_found: ask the user; never guess' — which tells the agent what to do when resolution fails. The 'Several accounts: see fix' branch points somewhere useful but the referent ('fix') is opaque and not a listed sibling, weakening the routing.

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.

NameRequiredDescriptionDefault
group_idYes<id>@g.us
account_idNo

Output 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

A3.7/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive/openWorld, and the description adds useful context beyond them: a 500-participant cap and the fact that the invite link is only returned for an admin (an auth-conditional detail). It does not discuss pagination or failure modes, but the added constraints are valuable.

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?

It fits the essential information into one dense sentence with no wasted words, and the sequencing cue lands at the end. It reads as a return-value list rather than a front-loaded purpose statement, but nothing is superfluous.

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 an output schema present, the return enumeration is technically redundant but helpful, and annotations cover the safety profile. The only real gap is the unexplained account_id, but otherwise an agent has enough to call it correctly.

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

Parameters2/5

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

At 50% schema coverage, only group_id is documented ('<id>@g.us') while account_id is undocumented in both schema and description. The description adds no parameter meaning to compensate, leaving account_id's role ambiguous from the definition alone.

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 enumerates exactly what the tool returns (name, description, owner, participants, settings, community, invite link), making the retrieval purpose clear. It also implies a read-only scope distinct from manage_group. It never quite states a leading verb, but an agent knows what it gets back.

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 an explicit sequencing rule: 'Call it before manage_group,' which tells the agent when this precedes a mutation. It does not name alternatives or when-not conditions, but the primary usage context is clear.

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; a copy kept on arrival answers first. MEDIA_UNAVAILABLE: gone, none kept.

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

Output Schema

NameRequiredDescription
mimeNo
pathNo
sizeNo
typeYes
senderYes
sourceNokept: the copy wazap kept when it arrived; whatsapp: downloaded now
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?

Beyond the annotations (readOnlyHint/not destructive, openWorld), the description adds genuinely useful behavior: transcripts are billed by an API provider, save_to writes a file to the local machine, and a MEDIA_UNAVAILABLE outcome means the media is gone. These cost and failure-mode disclosures are exactly what annotations cannot convey, though the save_to disk-write side effect on a 'read-only' tool could have been called out more explicitly.

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?

It is short, but the elliptical fragments ('a photo attached as an image; any file saved at path on the machine running wazap; a copy kept on arrival answers first') are dense and hard to parse on first read, so compactness comes at the cost of clarity.

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?

An output schema exists so return values need not be spelled out, and the description covers media variants and the MEDIA_UNAVAILABLE case. However, for a tool that takes an account_id and writes files via save_to, the absence of any note on account scoping or where files land by default leaves real gaps.

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 50%: save_to and language are documented in the schema, and the description reinforces save_to's effect ('with save_to its file'), while message_id and account_id receive no explanation anywhere. With half the parameters undocumented, the description only partially compensates.

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 phrase 'What a message's media holds' plus the enumeration (transcript, image, file) makes clear it fetches a message's attachments, but there is no verb-led statement of the action and no differentiation from the sibling get_message, which an agent could easily confuse it with.

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?

No explicit when-to-use or when-not-to-use guidance is given, and nothing says to prefer this over get_message or search. The only routing-like hint, 'a copy kept on arrival answers first,' concerns caching order, not tool selection, so usage must be inferred.

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, its words never cut: 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.

NameRequiredDescriptionDefault
account_idNo
message_idYes

Output Schema

NameRequiredDescription
textYes
chat_idYes
timestampYes
account_idYes
message_idYes

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety profile is covered. The description adds one genuinely useful behavioral fact: without account_id the id is looked up across every account. The rest is a return-content inventory (quotes, reactions, poll votes, media, read receipts) that an existing output schema already carries.

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?

A single dense sentence front-loads the core promise ('One message in full') and then enumerates contents efficiently. The only waste is the return-content inventory, which duplicates what the output schema already declares.

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 an output schema present, return values need little prose, and the annotations cover the safety profile; the only real gap an agent would care about is the lack of routing guidance versus read_messages or search. The account_id fallback note fills the other notable hole.

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 0%, so the description must carry parameter meaning, and it does explain account_id's optionality and its cross-account fallback behavior. message_id is left to the name and its minLength constraint, so the compensation is only partial.

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 title and the opening 'One message in full' state the specific resource and scope, and 'one message' implicitly separates it from bulk readers like read_messages. The description text itself, though, never says the verb plainly and never names a sibling to distinguish against, leaving the differentiation to the title.

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?

There is no explicit when-to-use or when-not-to-use guidance and no named alternative among siblings such as read_messages or search. That this is the single-message, full-fidelity fetch is only implied by 'One message in full'.

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.

NameRequiredDescriptionDefault
account_idNo
include_pictureNoAdd picture_url, the account's own profile photo (the link expires)

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds some useful context about what is inspected (sync, history freshness, webhook delivery, versions) and that accounts are listed with a default. It says nothing about authentication requirements, rate limiting, or failure behavior when the account is unreachable.

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?

It is short and the most useful content (the return-field inventory) comes first, but the structure is telegraphic: a colon list inside a sentence fragment with a trailing ellipsis, followed by a non-sequitur about accounts. Tightening into two clean sentences would cost nothing and read much better.

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?

There is no output schema, so the enumeration of returned data (status, sync, history freshness, webhook delivery, versions, accounts) carries real weight and is the strongest part. What is missing is the meaning of the enumerated status values and of account_id, which an agent needs to act on the result rather than just fetch 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?

Schema coverage is 50%: include_picture is documented in the schema (including the expiring link), but account_id has no description anywhere. The phrase "accounts lists every account, with default" hints at default-account behavior but never states what account_id defaults to or how it selects an account, so the description only partially compensates for the gap.

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 makes clear this is a health/diagnostic read of the account: connection status, sync progress, history freshness, webhook delivery, versions, and the account list with the default marked. It is distinguishable from siblings like list_chats or link_account, though the verb is implied rather than stated ("Whether the account works") and the parenthetical with an ellipsis is loose.

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 trigger conditions: "Call it on NOT_CONNECTED, NOT_LINKED or SYNC_IN_PROGRESS." That is more than most definitions offer. However, those state names are never defined or sourced, and no alternative is named for the NOT_LINKED case (link_account is an obvious sibling that is not mentioned).

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.

NameRequiredDescriptionDefault
account_idNo

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already cover readOnly/idempotent/non-destructive/closed-world, and the description adds the meaningful behavioral point that the call has zero effect on the WhatsApp account itself. It also signals the content categories (ids, workflows, error codes), which is useful for judging whether to call it first, though it doesn't specify the response shape or size.

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?

One dense sentence that front-loads the topics covered and ends with the strongest routing cue ('read it once, before the other tools'). No filler and every clause carries information.

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 single-optional-parameter documentation tool with no output schema, the description supplies everything needed: what the guide contains, the account scoping rule, the recommended call order, and confirmation of no side effects.

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 0% — account_id is an unexplained bare string — and the description compensates by explaining that account_id matters when several accounts are in play. It does not clarify when the parameter can be omitted despite being optional, which keeps it short of a 5.

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?

A specific resource is named — a guide covering ids, account_id semantics for multi-account setups, workflows, message shape, and error codes — and 'it never touches WhatsApp' immediately distinguishes it from every action sibling. An agent can tell this is documentation retrieval, not an API call, without opening the schema.

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?

'Read it once, before the other tools' gives explicit ordering guidance relative to the 22 sibling tools, and the exclusion ('never touches WhatsApp') tells the agent not to expect any live data or side effects. Both when-to-use and what-it-is-not are stated.

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.

NameRequiredDescriptionDefault
tagNoOnly chats with people filed under this tag
limitNo
cursorNoOpaque next_cursor from the preceding page; keep the same filter
filterNo"all" leaves out archivedall
account_idNo
include_picturesNoAdd picture_url, each chat's profile photo (links expire)

Output Schema

NameRequiredDescription
tagNo
syncYes
chatsYes
countYes
filterYes
account_idYes
next_cursorNo

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive), so the description only needed to add context beyond that. It does: result ordering, the set of surfaced fields, and the presence of archived/pinned/muted/left flags. It says nothing about page size behavior or what happens when the account has no chats, so it stops short of a 5.

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 tight sentences, front-loaded with what comes back and ordering, ending with the actionable purpose. The field enumeration is somewhat redundant given an output schema exists, but it earns its place by letting an agent judge suitability at a glance.

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?

Return values needn't be explained since an output schema exists, and the description covers ordering and flags. Gaps remain around pagination expectations (limit/cursor are only sketched in the schema), the required account_id, and how this differs from search or list_contacts — for a 6-parameter tool that's the minimum viable level.

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 sits at 67% and the description mentions no parameters at all — tag, filter, cursor, and include_pictures are documented only in the schema, while limit and account_id are undocumented in both places. With the majority of parameters covered by structured fields, the baseline of 3 is right, but the description adds no semantic lift.

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?

States the specific resource (chats/conversations), the ordering (most recently active first), and the fields returned, plus the concrete downstream purpose (find a chat_id). It does not distinguish itself from siblings like search or find_contact, which is the only thing keeping it from a 5.

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?

"Use it to find a chat_id" gives one concrete use case, which implies this is the discovery/listing entry point. But there are no exclusions or comparisons to alternatives such as search or list_contacts, so the agent must infer when this beats a search.

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

list_contactsList the phone's address bookA
Read-onlyIdempotent

The phone's address book on one account, a page at a time: saved name, phone (E.164), chat_id, contact_id, and when the last direct message was and its direction. No message words; #private people left out. address_book_synced false: not arrived yet.

NameRequiredDescriptionDefault
limitNo
orderNorecent: latest direct chat first, then the rest in address book orderrecent
cursorNonext from the previous page
account_idNo

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already declare it a safe, idempotent, open-world read, yet the description still adds real context: results arrive a page at a time, contacts with direct messages excluded from output are omitted, and 'address_book_synced false' means the book has not finished syncing. It adds value beyond the annotations without contradicting them.

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?

Front-loaded with the resource and the returned fields, then the exclusions, then the sync caveat — a logical order with no filler. The telegraphic fragments are dense but each clause carries information.

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 no output schema, the description responsibly enumerates the returned fields (name, E.164 phone, chat_id, contact_id, last DM timestamp/direction). The main residual gap is ordering and page-size behavior, which the schema only partly covers.

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 only 50% — 'order' and 'cursor' are documented inline, but 'limit' and 'account_id' are bare. The description gestures at both gaps ('on one account' implies account scoping, 'a page at a time' implies cursor/limit) but gives no default, maximum, or cursor-lifetime detail, so it only partially compensates.

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 names a specific resource (the phone's address book, scoped to one account) and states it is paginated. It is clearly a listing operation, distinguishable from find_contact or list_chats by its roster-of-contacts framing, though it never names a sibling explicitly.

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?

Usage is only implied: the reader infers this is for enumerating contacts and that find_contact is the lookup alternative. There is no explicit when-to-use/when-not statement, and the '#private people left out' note scopes the output rather than the call decision.

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

Preview archive, pin, mute, pin_message, star_message, clear, delete, block and undo. After approval repeat chat_id/action with confirmation_id, without options. Expires in 15m; one attempt. mark_read runs directly.

NameRequiredDescriptionDefault
actionYes
chat_idYesChat id, or a phone number
pin_hoursNopin_message: 168 by default
account_idNo
message_idNopin_message, star_message and their undo; in chat_id
mute_hoursNomute: 8 by default
confirmation_idNoFrom preview; omit message/duration options

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and non-idempotent, and the description adds genuinely new operational facts: a 15-minute expiry, a single attempt per confirmation, and that optional options must be dropped on the confirming call. It does not say what 'clear' versus 'delete' actually removes, which is the one behavioral detail an agent would still want.

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?

Four short sentences with the approval flow and expiry front-loaded and no filler. The telegraphic action list reads as a fragment, but nothing in it is wasted.

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?

For a 16-action, destructive, no-output-schema tool, the description covers the approval mechanics but leaves the action taxonomy under-specified (undo variants and mark_unread unlisted, clear vs. delete undefined) and never states that preview returns a confirmation_id. Adequate to call correctly, but an agent could still mis-select an action.

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?

With 71% schema description coverage, the schema already documents chat_id, message_id, pin_hours, mute_hours and confirmation_id. The description adds the sequencing rule (confirmation call carries only chat_id/action, no options), which is real value, but it never ties message_id to pin_message/star_message or explains which optional parameters pair with which of the 16 enum actions.

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 enumerates the concrete chat operations it fronts (archive, pin, mute, pin_message, star_message, clear, delete, block) and signals a preview-then-confirm shape, so an agent can tell it apart from siblings like manage_group or delete_message. It is slightly incomplete — the un* variants (unarchive, unpin, unblock) and mark_unread are never named, and the mutated resource ('chat') is only implied by the title.

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 two-phase flow is spelled out: first call previews, then 'repeat chat_id/action with confirmation_id', and 'mark_read runs directly' carves out the exception that skips approval. It lacks any guidance on when to prefer this over siblings such as manage_group or delete_message, so the routing context is only partially covered.

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.

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_idNo
message_idNojoin: an invite message instead
participant_idsNocreate, add, remove, promote, demote, approve or reject

Output 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.2/5.0
Behavior4/5

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

Annotations already flag mutation, destructiveness, open-world behavior, and non-idempotence. The description adds important context beyond them: admin authorization is usually required, and every change is visible to all members, with a consent workflow. It does not distinguish which of the many actions are especially destructive or irreversible.

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 tight sentences, front-loaded with the three usage modes and followed by the key admin and group-wide side-effect constraints. Every sentence carries useful selection or invocation information.

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 complex 21-action tool with an output schema and rich annotations, the description covers the operations, admin prerequisite, join preview/confirm flow, and group-wide side effects. It reasonably relies on the schema for per-action parameter mapping, though it could say more about which actions require particular parameters.

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 80%, so the input schema already documents most parameters. The description maps action categories and mentions the invite/preview/confirm workflow, but adds little format or syntax 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?

The description opens with specific verbs and resources: create a group, join from an invite, and administer members, name, description, photo, invite link, join requests, settings, and leave. This clearly separates it from read-oriented siblings like get_group_info and message-oriented 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?

It gives concrete usage conditions: join requires a preview then confirm: true, most actions need admin, and group-wide changes require telling users and waiting for yes. It does not name sibling alternatives or say when not to use this tool, so it falls short of a 5.

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.

NameRequiredDescriptionDefault
emojiYes
account_idNo
message_idYes

Output Schema

NameRequiredDescription
emojiYes
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 declare this is a non-read-only, non-destructive, idempotent, open-world operation. The description adds useful behavior beyond that: only one emoji is allowed, and an empty string removes the existing reaction.

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 front-loaded sentence with no wasted words. Both the main action and the removal behavior are stated efficiently.

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 is simple, has an output schema, and has annotations covering safety and idempotency. The description covers the core behavior sufficiently, though account_id and message_id semantics are left implicit.

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 0%, so the description must carry parameter meaning. It explains the emoji parameter well, including empty-string removal semantics, but does not explain message_id or account_id beyond their names in 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 states a specific verb and resource: reacting to a WhatsApp message. It also distinguishes the add-reaction and remove-reaction cases, so an agent can tell it apart from siblings like send_message, edit_message, or 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 Guidelines4/5

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

The description clearly explains the two usage modes: pass one emoji to react, or pass an empty string to remove the reaction. It does not explicitly name alternatives, but the context is clear enough for this narrow operation.

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). Long texts are cut unless full_text. chat_id "status" reads the stories people posted, newest first, from the last hours (at most a day); they show nowhere else.

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
full_textNoEach message's text whole; a list cuts long ones otherwise
account_idNo
include_previewsNoAttach a small image of each photo, up to 12

Output 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.3/5.0
Behavior4/5

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

Annotations already establish readOnly/idempotent/openWorld, and the description adds real behavior the annotations don't: history gaps trigger a phone fetch (latency/implication), long texts are truncated unless full_text, and status items are ephemeral (max a day) and appear nowhere else. It does not cover error modes or rate limits, so not a full 5.

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?

Dense and front-loaded, with the main retrieval model in the first clause and the status special case after. The prose is slightly idiosyncratic ("wazap asks the phone") but every sentence carries information, so nothing is wasteful.

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 an output schema exists and annotations cover the safety profile, the description covers the non-obvious essentials: pagination, truncation, and the stories mode. The main gap is account_id (multi-account selection), which is undocumented in both the schema and the description.

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?

With 75% schema coverage the baseline is 3, and the description genuinely adds value: it explains the before-based pagination model, the truncation default that full_text overrides, and that "status" is a special chat_id value. `limit`, `types` and `account_id` are left to the schema (account_id is undescribed in both places).

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?

Opens with a specific verb and resource plus scope: "Read one chat, oldest to newest." It also carves out the special "status" mode for stories, which an agent could not infer from the name. Together these let an agent tell it apart from search, get_message, list_chats and wait_for_messages.

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?

Clear context for the two main modes: fetch the latest messages, or page backwards using `before` once you have the oldest message_id. It also flags that stories require chat_id "status" and are time-bounded. It stops short of explicitly naming when to prefer search, catch_up or wait_for_messages instead.

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.

NameRequiredDescriptionDefault
noteNo"" removes it
fieldsNoe.g. {"nickname": "Mișu", "role": "contabil"}; "" deletes a key
chat_idYesSeveral: tags and fields only
handledNoOff catch_up's waiting until they write again
add_tagsNoe.g. ["client"]
account_idNo
remove_tagsNo
remove_fieldsNo

Output Schema

NameRequiredDescription
nameNo
noteNo
tagsNo
fieldsNo
numberNo
peopleNoSeveral chat_ids: each one's card
chat_idNo
handledNoThe ask taken off the waiting list; null when nothing was open
account_idYes
is_businessNo
is_my_contactNo

TDQS

A3.5/5.0
Behavior4/5

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

Annotations already declare non-read-only, idempotent, non-destructive, closed-world behavior, so the bar is lower, and the description still adds genuinely new context: storage is local and never written to WhatsApp, and the privacy flags alter how the record is exposed in later reads. The explanation of #private ('keeps their words out of what you did not ask about them by name') is confusing enough to blunt the value, but the disclosure is substantive.

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 core constraint (local, never on WhatsApp) is front-loaded, and there is little outright filler. But the single run-on sentence stacks four distinct payload types and two hashtag modifiers into one breath, making it harder to parse than it needs to be.

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?

An output schema exists, so return values need no explanation, and the annotations cover the safety profile. Still, for an 8-parameter mutation tool with nested objects, the description leaves gaps: precedence when note/fields/add_tags/remove_tags are combined, behavior on a chat_id array (only 'tags and fields only' is hinted), and the relationship to the 'learn' sibling.

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 63%, so the schema carries most of the burden, and the description does add meaning for 'fields' by tying it to what find_contact matches, plus the deletion semantics for note. It says nothing about account_id, remove_tags, remove_fields, or the array form of chat_id beyond the schema's own note, so it only partially compensates for the coverage gap.

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?

States a specific verb and resource ('Keep what the user says about someone, locally') and enumerates what can be stored: note, tags, matched details, and the handled flag. It also implicitly distinguishes itself from send_message by saying 'never on WhatsApp'. The phrasing is compressed and jargon-heavy, but an agent can identify the operation.

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 conditional guidance for two cases ('handled: true for an ask dealt with elsewhere', '#no-catchup keeps them out of catch_up'), which is real when-to-use signal. However, it never explains how this differs from the sibling tool 'learn', nor does it state prerequisites such as a linked account or what happens on conflicting writes. Usage is implied rather than fully specified.

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

reminderSet, list or cancel a reminder about a chatA

The user's reminders about a chat, kept locally and posted to their webhook when due: create (chat_id, note, after_hours or due_at); condition "no_reply" fires only if nobody wrote there since ("if Ana has not answered in 2 days"). list, cancel. Nothing goes to WhatsApp.

NameRequiredDescriptionDefault
noteNocreate: what to remind the user of
limitNo
actionNolist
due_atNocreate: due then, "2026-10-14T09:00" in time_zone, or with an offset
chat_idNocreate: the chat it is about
conditionNono_reply: skipped if someone wrote in the chat after it was setalways
time_zoneNoIANA zone for due_at; the server's by default
account_idNo
after_hoursNocreate: due this many hours from now
reminder_idNocancel: from create or list
include_closedNolist: the week's fired, skipped and cancelled ones too

Output Schema

NameRequiredDescription
countYes
notesNoCaveats to act on or tell the user
actionYes
cancelledNo
remindersYes
account_idYes

TDQS

A3.8/5.0
Behavior4/5

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

Beyond the annotations (readOnlyHint=false, destructiveHint=false, openWorldHint=false), the description discloses where state lives (kept locally), how it is delivered (posted to the user's webhook when due), and a crucial side-effect exclusion ('Nothing goes to WhatsApp'). It does not say whether cancel is recoverable or what happens to already-fired reminders, so it is strong but not exhaustive.

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 core framing (what it is, where it lives, how it fires) is front-loaded in the first clause, and there is no filler. The mid-sentence parentheticals and semicolon-joined fragments make it slightly telegraphic, but every clause carries information an agent needs.

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 an 11-parameter, three-action tool with an output schema and annotations in place, the description covers the action surface, the timing model and the delivery mechanism sufficiently to call it correctly. Remaining gaps (account_id scoping, pagination via limit, cancel irreversibility) are low-risk and largely covered by the schema.

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 73%, so some compensation is expected, and the description does add meaning: it maps action values to the parameters they consume (create: chat_id, note, after_hours or due_at) and gives a human-readable gloss of the 'no_reply' condition that goes beyond the schema's terse wording. It leaves account_id, limit, include_closed and reminder_id provenance to 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 names the resource (the user's reminders about a chat) and the three supported actions (create, list, cancel) with the key create parameters spelled out. It also implicitly distinguishes itself from messaging siblings by stating reminders are kept locally and 'Nothing goes to WhatsApp'. It stops short of naming a specific sibling tool it supersedes, so not a 5.

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 clarifies the two scheduling modes (after_hours vs due_at) and explains when the 'no_reply' condition fires, with a concrete natural-language example. However, it never states when an agent should pick this tool over a nearby alternative such as scheduled_messages, nor does it state prerequisites for cancel (a reminder_id from create or list). Usage context is implied rather than prescribed.

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

scheduled_messagesList or cancel scheduled WhatsApp messagesA
Idempotent

The account's scheduled messages: list (waiting ones soonest first, then the week's sent, missed, failed and cancelled ones) or cancel one by schedule_id before it goes. To schedule one, send_message with send_at, then confirm_send. Tell the user about every missed or failed one.

NameRequiredDescriptionDefault
limitNo
actionNolist
account_idNo
schedule_idNocancel: from the list or confirm_send
include_closedNolist: the week's sent, missed, failed and cancelled ones too

Output Schema

NameRequiredDescription
countYes
actionYes
cancelledNo
scheduledYes
account_idYes

TDQS

A4.4/5.0
Behavior4/5

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

The annotations already indicate this is not read-only because cancellation is possible, and the description adds useful behavior: listing order, cancellation before send, and a user-notification requirement for missed/failed messages. It does not contradict the annotations, though it leaves permission and failure behavior for cancellation unstated.

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: it presents the list/cancel choice first, then the scheduling alternative, then the notification requirement. Every sentence adds operational 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?

For a two-action tool with an output schema, this is largely complete: it covers what list returns, how cancel is targeted, and how scheduling relates to sibling tools. The main gap is that limit and account_id are not discussed.

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 40%, so the description should compensate more. It clarifies action modes, schedule_id for cancellation, and include_closed via the week’s sent/missed/failed/cancelled items, but it does not explain limit or account_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?

The description states specific verbs and resource: list or cancel scheduled WhatsApp messages. It distinguishes itself from scheduling siblings by directing users to send_message with send_at followed by confirm_send.

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?

It explains both modes explicitly: use list to see scheduled messages and cancel with schedule_id before sending. It also names the alternative workflow for creating a scheduled message and instructs the agent to tell the user about missed or failed messages.

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.

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
send_atNoSend later: "2026-10-12T09:00" in time_zone, or with an offset; 1 minute to 365 days ahead
latitudeNo
reply_toNo
file_pathNoMedia: absolute path on the machine running wazap
longitudeNo
time_zoneNoIANA zone for send_at, e.g. "Europe/Bucharest"; the server's by default
account_idNo
mention_idsNoChat ids to @-mention; write @<number> in text for each
multi_selectNoPoll: several answers allowed

TDQS

A4.4/5.0
Behavior4/5

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

Adds substantial context beyond the annotations: no message leaves the system, the call returns draft_id plus a preview covering recipient, number and exact text, and the preview must be shown before confirm_send. It does not cover rate limits or per-media-type side effects, so it stops short of 5, but the highest-risk behavior (accidental send) is fully disclosed.

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 dense sentences, front-loaded with the non-sending guarantee before the workflow. Every clause carries instruction the agent needs — the trigger condition, the return payload, and the confirmation gate — with no restatement of the title or schema.

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 16-parameter drafting tool with no output schema, the description supplies the missing return-value summary (draft_id and preview) and the confirmation protocol, which is the critical gap. It is slightly thin on the scheduled-send and mention paths, though those are covered by schema descriptions.

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 75% and the schema already documents per-parameter meaning including the empty-text convention for forwards, so the baseline of 3 applies. The description only names the two required inputs in passing and adds nothing about send_at scheduling, time_zone, mention_ids or account_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?

Opens with a specific verb and enumerated resource types ("Drafts text, media, polls, locations, forwards") and immediately bounds scope with "sends nothing." That clause alone separates it from the sibling confirm_send and edit_message without opening either schema.

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 an explicit trigger ("Call it as soon as you have recipient and text") and an explicit routing rule to the alternative ("confirm_send only on a yes to this text and recipient"). It even resolves an ambiguous case — a send in the same request counts as the yes — leaving nothing to inference.

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.

NameRequiredDescriptionDefault
cursorNoFrom the previous call
chat_idNoChat id, or a phone number
account_idNo
addressed_to_meNo
timeout_secondsNo

Output 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

A3.8/5.0
Behavior4/5

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

Annotations already cover readOnly, idempotent, open-world and non-destructive, so the safety profile is done. The description adds genuinely non-obvious behavior: the call blocks for up to timeout_seconds, returns a cursor whose reuse prevents gaps between calls, and addressed_to_me narrows wake-ups to DMs, mentions and replies. It omits what is returned when the timeout elapses with no messages, which is the main behavioral gap.

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?

Front-loaded with the core action and its timing constraint, then the cursor contract, then the filter. Three dense clauses with no repetition of annotations. 'For agents that stay on the line' is a slightly decorative closer, but it frames the intended usage rather than wasting space.

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?

Return values are covered by the existing output schema, and the crucial cross-call cursor contract is spelled out, which is what an agent needs to loop correctly. Missing only the empty-timeout outcome and any guidance on chat_id/account_id scoping; for a 5-param, zero-required tool that is close to complete.

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 only 40%, so the description must compensate, and it does for three of five params: cursor provenance, addressed_to_me's exact semantics, and timeout_seconds as an upper bound. chat_id and account_id are left to the schema (chat_id has a description there, account_id has none), which is a minor shortfall rather than a blocker.

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?

States a specific verb and resource ('wait for messages'), plus scoping ('from other people, up to timeout_seconds') and a distinguishing long-poll mechanism (cursor returned and passed back). It does not name the close siblings read_messages or catch_up, so an agent must infer the difference, but the 'wait/block' semantics separate it from the fetch tools.

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?

'For agents that stay on the line' and 'pass it to the next call so nothing... is missed' imply the streaming/long-poll use case, but there is no explicit when-to-use-vs-alternatives guidance — nothing says to prefer read_messages for a one-shot fetch or catch_up for backlog. Usage is inferable rather than stated.

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. 23 tool updatesv1.6.0
    • Changedcatch_up3 fields changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
      • addedOutput schema / properties / direct / items / properties / tags
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / waiting / items / properties / tags
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
    • Changedconfirm_send1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changeddelete_message1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changededit_message1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedfind_contact1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedget_group_info1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedget_media1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedget_message1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedget_status1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedlearn1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedlink_account1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedlist_chats3 fields changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
      • addedInput schema / properties / tag
        Added value: +{
        +  "description": "Only chats with people filed under this tag",
        +  "maxLength": 40,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedOutput schema / properties / tag
        Added value: +{
        +  "type": "string"
        +}
    • Changedlist_contacts1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedmanage_chat2 fields changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
      • addedInput schema / properties / confirmation_id
        Added value: +{
        +  "description": "From preview; omit message/duration options",
        +  "maxLength": 64,
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changedmanage_group1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedreact_to_message1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedread_messages1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedremember7 fields changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
      • addedInput schema / properties / chat_id / anyOf
        Added value: +[
        +  {
        +    "description": "Chat id, or a phone number",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  {
        +    "items": {
        +      "$ref": "#/properties/chat_id/anyOf/0"
        +    },
        +    "maxItems": 50,
        +    "minItems": 1,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / chat_id / description
        Previous value: -"Chat id, or a phone number"New value: +"Several: tags and fields only"
      • removedInput schema / properties / chat_id / minLength
        Removed value: -1
      • removedInput schema / properties / chat_id / type
        Removed value: -"string"
      • addedOutput schema / properties / people
        Added value: +{
        +  "description": "Several chat_ids: each one's card",
        +  "items": {
        +    "additionalProperties": true,
        +    "properties": {},
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "chat_id",
        -  "name",
        -  "account_id"
        -]New value: +[
        +  "account_id"
        +]
    • Changedreminder1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedscheduled_messages1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedsearch21 fields changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
      • addedInput schema / properties / before
        Added value: +{
        +  "description": "Older lexical matches; auto uses words with a cursor",
        +  "minLength": 5,
        +  "type": "string"
        +}
      • addedInput schema / properties / include_context
        Added value: +{
        +  "default": true,
        +  "description": "Nearby sources for the best five hits",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / match / default
        Previous value: -"hybrid"New value: +"auto"
      • changedInput schema / properties / match / description
        Previous value: -"\"words\": only messages holding the words"New value: +"auto: questions by meaning, codes/quotes by words"
      • changedInput schema / properties / match / enum
        Previous value: -[
        -  "hybrid",
        -  "words"
        -]New value: +[
        +  "auto",
        +  "hybrid",
        +  "words"
        +]
      • addedInput schema / properties / tag
        Added value: +{
        +  "description": "Only chats with people filed under this tag",
        +  "maxLength": 40,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedOutput schema / properties / assessment
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "note": {
        +      "type": "string"
        +    },
        +    "state": {
        +      "enum": [
        +        "no_matches",
        +        "ambiguous",
        +        "candidates"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "state",
        +    "note"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / changed_during_read
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / contexts
        Added value: +{
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "anchor_id": {
        +        "type": "string"
        +      },
        +      "bounded": {
        +        "const": true,
        +        "type": "boolean"
        +      },
        +      "messages": {
        +        "items": {
        +          "additionalProperties": true,
        +          "properties": {
        +            "chat_id": {
        +              "type": "string"
        +            },
        +            "message_id": {
        +              "type": "string"
        +            },
        +            "text": {
        +              "type": "string"
        +            },
        +            "timestamp": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "message_id",
        +            "chat_id",
        +            "text",
        +            "timestamp"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      }
        +    },
        +    "required": [
        +      "anchor_id",
        +      "messages",
        +      "bounded"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / messages / items / properties / chat_id / $ref
        Added value: +"#/properties/contexts/items/properties/messages/items/properties/chat_id"
      • removedOutput schema / properties / messages / items / properties / chat_id / type
        Removed value: -"string"
      • addedOutput schema / properties / messages / items / properties / message_id / $ref
        Added value: +"#/properties/contexts/items/properties/messages/items/properties/message_id"
      • removedOutput schema / properties / messages / items / properties / message_id / type
        Removed value: -"string"
      • addedOutput schema / properties / messages / items / properties / rank_score
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / messages / items / properties / text / $ref
        Added value: +"#/properties/contexts/items/properties/messages/items/properties/text"
      • removedOutput schema / properties / messages / items / properties / text / type
        Removed value: -"string"
      • addedOutput schema / properties / messages / items / properties / timestamp / $ref
        Added value: +"#/properties/contexts/items/properties/messages/items/properties/timestamp"
      • removedOutput schema / properties / messages / items / properties / timestamp / type
        Removed value: -"string"
      • addedOutput schema / properties / next_before
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "query",
        -  "mode",
        -  "count",
        -  "messages",
        -  "freshness",
        -  "sync",
        -  "account_id"
        -]New value: +[
        +  "query",
        +  "mode",
        +  "count",
        +  "assessment",
        +  "messages",
        +  "freshness",
        +  "sync",
        +  "account_id"
        +]
    • Changedsend_message1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
    • Changedwait_for_messages1 field changed
      • removedInput schema / properties / account_id / description
        Removed value: -"Account id"
  2. 1 tool updatev1.4.2
    • Changedlist_chats2 fields changed
      • addedInput schema / properties / cursor
        Added value: +{
        +  "description": "Opaque next_cursor from the preceding page; keep the same filter",
        +  "maxLength": 512,
        +  "type": "string"
        +}
      • addedOutput schema / properties / next_cursor
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
  3. 9 tool updatesv1.4.0
    • Changedconfirm_send1 field changed
      • changedInput schema / properties / draft_id / description
        Previous value: -"From send_message"New value: +"From send_message; one with send_at is scheduled, not sent"
    • Changedget_media1 field changed
      • addedOutput schema / properties / source
        Added value: +{
        +  "description": "kept: the copy wazap kept when it arrived; whatsapp: downloaded now",
        +  "enum": [
        +    "kept",
        +    "whatsapp"
        +  ],
        +  "type": "string"
        +}
    • Changedget_status1 field changed
      • addedInput schema / properties / include_picture
        Added value: +{
        +  "default": false,
        +  "description": "Add picture_url, the account's own profile photo (the link expires)",
        +  "type": "boolean"
        +}
    • Changedlist_chats1 field changed
      • addedInput schema / properties / include_pictures
        Added value: +{
        +  "default": false,
        +  "description": "Add picture_url, each chat's profile photo (links expire)",
        +  "type": "boolean"
        +}
    • Changedread_messages1 field changed
      • addedInput schema / properties / full_text
        Added value: +{
        +  "description": "Each message's text whole; a list cuts long ones otherwise",
        +  "type": "boolean"
        +}
    • Addedreminder
    • Addedscheduled_messages
    • Changedsearch1 field changed
      • addedInput schema / properties / full_text
        Added value: +{
        +  "description": "Each message's text whole; a list cuts long ones otherwise",
        +  "type": "boolean"
        +}
    • Changedsend_message2 fields changed
      • addedInput schema / properties / send_at
        Added value: +{
        +  "description": "Send later: \"2026-10-12T09:00\" in time_zone, or with an offset; 1 minute to 365 days ahead",
        +  "maxLength": 40,
        +  "minLength": 10,
        +  "type": "string"
        +}
      • addedInput schema / properties / time_zone
        Added value: +{
        +  "description": "IANA zone for send_at, e.g. \"Europe/Bucharest\"; the server's by default",
        +  "maxLength": 64,
        +  "minLength": 1,
        +  "type": "string"
        +}
  4. 1 tool updatev1.2.0
    • Addedlist_contacts
  5. 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"
        +}
  6. 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
  7. 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
  8. 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
  9. 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.6/5.0

Scored across 23 tools

Disambiguation4/5

Most tools target a clear, distinct resource and action (list_chats vs read_messages vs search vs catch_up are well separated, and send_message/confirm_send are explicitly staged). A few pairs could be lightly confused at a glance — remember vs reminder, find_contact vs list_contacts, manage_chat vs manage_group — but descriptions draw the boundaries clearly.

Naming Consistency4/5

Consistent snake_case throughout, with a dominant verb_noun pattern (get_status, list_chats, read_messages, confirm_send, manage_group, edit_message). Minor deviations exist in noun-form tools (reminder, scheduled_messages) and bare verbs (learn, remember, search, catch_up), but nothing ambiguous.

Tool Count4/5

23 tools is on the heavy side, but the domain genuinely spans messaging, media, contacts, groups, scheduling, reminders, memory and account linking. Each tool covers a distinct capability, so the surface is broad rather than padded.

Completeness4/5

Strong lifecycle coverage: draft/confirm send, read, search, edit, delete, react, media, contacts, groups, scheduling and account linking. Minor gaps like profile/account settings management and explicit quoting/forwarding details (partially folded into send_message/get_message) keep it from a 5.

Maintenance

ActivityActive
ResponsivenessSlow

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    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.
    26
    MIT
  • A
    license
    Not graded
    quality
    B
    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.
    4
    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.
    3 npm
    1
    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.
    6 npm
    1
    MIT