Skip to main content
Glama
razvangirgiz

wazap-mcp

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

WhatsApp для вашего ИИ-агента. MCP-сервер, который предоставляет ваш аккаунт WhatsApp — чаты, сообщения, медиа, контакты, группы — через 22 инструмента, которые может вызывать любой MCP-клиент. Вход по коду сопряжения, без браузера, без перепродажи номеров телефонов, ~20 МБ ОЗУ.

Построен на Baileys, который говорит на мультиустройственном протоколе WhatsApp через WebSocket.

Начало работы

npm-пакет называется wazap-mcp; команда, которую он устанавливает, — wazap.

npx wazap-mcp setup

Это вся установка. Она связывает ваш аккаунт, находит MCP-клиентов, установленных на этой машине, записывает их конфигурацию и сообщает, что нужно перезапустить.

Или пусть это сделает ваш агент. Вставьте это:

Настрой мне WhatsApp: выполни npx wazap-mcp setup --agent и следуй тому, что он выведет.

Затем спросите агента: «Что я пропустил в WhatsApp сегодня?»

Ниже приведены шаги, которые setup выполняет за вас. Каждый из них — отдельная команда, если вы хотите выполнить её вручную.

npx wazap-mcp login показывает QR-код; отсканируйте его в Настройки → Связанные устройства → Привязать устройство. Нет камеры под рукой или связывание через SSH? npx wazap-mcp login --phone +15550100 выводит 8-значный код, который вы вводите в разделе Привязать по номеру телефона. В конце он спрашивает, может ли агент отправлять сообщения; ответ «нет», если вы не скажете «да», а npx wazap-mcp config writes on изменит это позже.

npx wazap-mcp connect claude-code записывает запись MCP для одного клиента. Остальные — в таблице под Подключение клиента.

npx wazap-mcp сам по себе безопасен для запуска: он выводит, где вы находитесь и что делать дальше, и не запускает сервер. Если что-то не так, npx wazap-mcp status — первое, что нужно запустить: он проверяет Node, каталог данных, блокировку, учётные данные и наличие новой версии, а рядом с каждой проблемой выводит исправление.

Подключение клиента

wazap connect <client> записывает запись за вас, сохраняя всё остальное в файле и делая резервную копию один раз перед первым изменением. --dry-run показывает, что он запишет.

Клиент

Что записывает connect

claude-code

выполняет claude mcp add whatsapp за вас

claude-desktop

claude_desktop_config.json в каталоге приложения Claude

cursor

~/.cursor/mcp.json

codex

[mcp_servers.whatsapp] в ~/.codex/config.toml

vscode

./.vscode/mcp.json для текущей рабочей области

gemini

~/.gemini/settings.json

что-то удалённое

поле URL MCP клиента: https://your-host/mcp с заголовком Authorization: Bearer <token> (см. Сам хостинг)

Любой MCP-клиент работает одинаково: команда — npx -y wazap-mcp, транспорт — stdio. Скажите агенту сначала вызвать learn — он вернёт форматы идентификаторов, рабочие процессы и каждый код ошибки с указанием, что делать.

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

Claude Desktop, Cursor и Gemini CLI принимают именно это. VS Code вкладывает это в servers и требует "type": "stdio" рядом с command. Codex CLI — это TOML:

[mcp_servers.whatsapp]
command = "npx"
args = ["-y", "wazap-mcp"]

Папка skills/ соответствует формату Agent Skills, поэтому Codex, Cursor и другие агенты, поддерживающие навыки, могут загрузить те же пять навыков.

Related MCP server: wa-bridge

Инструменты

Инструмент

Вид

Что делает

learn

чтение

Руководство по каждому инструменту, формату идентификаторов и коду ошибки. Вызовите его первым.

get_status

чтение

Статус подключения, состояние синхронизации, связанный аккаунт, версии, каталог данных.

list_chats

чтение

Разговоры от новых к старым; фильтр all/unread/groups/individual/archived.

read_messages

чтение

Сообщения в чате; before листает дальше, подтягивая более старую историю с телефона.

get_recent_messages

чтение

Всё за последние N часов, сгруппированное по чатам. Инструмент для навёрстывания.

search_messages

чтение

Текстовый поиск по локально хранимым сообщениям.

get_message

чтение

Одно сообщение полностью, с цитируемым сообщением и реакциями.

search_contacts

чтение

Поиск контактов по имени или номеру.

get_contact

чтение

Имя, номер, текст «о себе», фото профиля.

get_group_info

чтение

Участники, администраторы, режим объявлений, ссылка-приглашение (если вы администратор).

download_media

чтение

Сохранить вложение на диск; небольшие изображения также возвращаются встроенно.

send_message

запись

Отправить текст, опционально как ответ, с @-упоминаниями.

send_media

запись

Отправить изображение, видео, аудио, голосовое сообщение или документ из пути или URL.

send_poll

запись

Отправить опрос с 2–12 вариантами.

send_location

запись

Отправить метку на карте.

edit_message

запись

Редактировать своё сообщение в течение 15-минутного окна WhatsApp.

react_to_message

запись

Добавить или удалить реакцию-эмодзи.

forward_message

запись

Переслать сообщение в другой чат.

delete_message

запись

Отозвать своё сообщение в течение 2-дневного окна WhatsApp.

manage_chat

запись

Архивировать, закрепить, заглушить (по умолчанию 8 часов), отметить прочитанным/непрочитанным.

create_group

запись

Создать группу и добавить участников.

manage_group

запись

Добавить, удалить, повысить, понизить, выйти, переименовать, ссылки-приглашения.

Каждое сообщение возвращается с непустым text: медиа- и системные сообщения содержат заполнитель, например [image] caption, [voice message], [deleted] или [poll] Pizza or pasta?. Временные метки — ISO 8601 со смещением UTC машины, рядом человекочитаемый age, например 2h ago.

Навыки

wazap поставляется с пятью Agent Skills, которые обучают агента рабочим процессам, стоящим за инструментами, а не только самим инструментам:

Навык

Что делает агент

wazap-setup

Диагностика с помощью wazap status, связывание по QR или коду сопряжения, подключение клиента с помощью wazap connect, восстановление истёкшей сессии

whatsapp-inbox

«Что я пропустил?» Сортировка на нужно вам / к сведению / шум, с ранжированием, плюс забытые ответы. Только чтение

whatsapp-recall

«Найди счёт, который отправил Дэн.» Поиск с вариантами запросов, листание назад во времени, загрузка и чтение файла. Только чтение

whatsapp-groups

Наверстать группу из 300 сообщений: решения, даты, что от вас требуется. Только чтение

whatsapp-send

Черновик в собственном регистре чата, показ получателя и текста, отправка только после согласия пользователя

Установите всё (сервер и навыки) как плагин Claude Code:

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

Или скопируйте skills/<name>/ в любой каталог навыков, который читает ваш агент.

Ошибки

Каждый сбой — это структурированный { error, message, fix }, а не трассировка стека, чтобы агент мог решить: повторить попытку, спросить пользователя или остановиться.

Код

Значение

NOT_LINKED

Аккаунт не связан. Выполните npx wazap-mcp login.

SESSION_EXPIRED

Отвязан от телефона. Выполните npx wazap-mcp login.

SESSION_CORRUPT

Учётные данные не читаются. Выполните npx wazap-mcp logout, затем login.

NOT_CONNECTED

Всё ещё подключается или переподключается.

SYNC_IN_PROGRESS

Синхронизация истории не завершена; результаты могут быть неполными.

INVALID_PHONE

Номер не в международном формате.

INVALID_ID

Не является идентификатором чата, контакта или группы WhatsApp.

NOT_ON_WHATSAPP

У этого номера нет аккаунта WhatsApp.

CHAT_NOT_FOUND / MESSAGE_NOT_FOUND / CONTACT_NOT_FOUND / GROUP_NOT_FOUND

Неизвестный идентификатор.

NOT_A_PARTICIPANT / NOT_ADMIN / GROUP_ANNOUNCEMENT_ONLY

Права в группе.

MEDIA_UNAVAILABLE

WhatsApp истёк срок файла, или он никогда не был синхронизирован здесь.

FILE_NOT_FOUND / FILE_TOO_LARGE / URL_FETCH_FAILED

Проблемы с исходящими медиа.

TEXT_TOO_LONG

Превышен лимит сообщений WhatsApp.

EDIT_WINDOW_EXPIRED / RETRACT_WINDOW_EXPIRED / NOT_OWN_MESSAGE

Собственные ограничения WhatsApp на редактирование и удаление.

READ_ONLY

wazap работает в режиме только для чтения.

RATE_LIMITED

Слишком много записей; fix указывает, сколько ждать.

TIMEOUT / WHATSAPP_ERROR

WhatsApp не ответил или отклонил операцию.

Каталог данных

Всё хранится в ~/.wazap (переопределяется с помощью --data-dir или WAZAP_DATA_DIR), создаётся с правами 0700, учётные данные записываются с правами 0600:

~/.wazap/
  auth/         WhatsApp credentials — treat this like a password
  media/        downloads from download_media
  history/      per-chat message history, so a restart is not amnesia
  store.json    chat-list snapshot
  server.lock   pid of the running server
  daemon.json   loopback endpoint a second wazap bridges to
  .env          optional settings, see .env.example

Запись учётных данных идёт во временный файл и затем переименовывается на место, поэтому убийство процесса во время записи не заставит вас заново связывать телефон.

Несколько клиентов одновременно

Claude Desktop, Claude Code и Cursor — каждый запускает собственный wazap. WhatsApp разрешает один сокет на привязанное устройство, поэтому они делят одну сессию, а не борются за неё. Первый wazap в каталоге данных владеет сессией и открывает MCP-эндпоинт на 127.0.0.1; каждый последующий подключается к нему через этот эндпоинт. Ничего настраивать не нужно, и ни один клиент не видит разницы. Владелец публикует <data-dir>/daemon.json (0600) со своим pid, своим портом и токеном, с которым мост аутентифицируется.

Мост обслуживает всё, что предоставляет владелец, поэтому владелец, запущенный с --read-only, делает каждого клиента доступным только для чтения, независимо от того, с какими флагами был запущен этот клиент.

Когда владелец выходит, мосты выходят вместе с ним, а следующий wazap, который запустит клиент, становится новым владельцем.

WAZAP_NO_SHARE=1 отключает это: второй wazap в том же каталоге завершается с кодом 2 и указывает pid уже запущенного. Явный --http — это самостоятельный сервер, а не мост, и ему отказывается так же.

Режим только для чтения

Запись — опциональна. login спрашивает один раз и сохраняет ответ в <data-dir>/.env; wazap config writes on|off меняет его, а один wazap config выводит все действующие настройки с указанием их источника.

WAZAP_READ_ONLY=1 или wazap serve --read-only вообще не регистрирует инструменты записи. Агент их никогда не видит, поэтому не может отправить сообщение с вашего номера даже по ошибке — полезно, когда привязанный аккаунт ваш личный.

Запись также ограничена по скорости до WAZAP_RATE_LIMIT в минуту (по умолчанию 20, 0 отключает). Отправка быстрее, чем человек, — это способ получить бан аккаунта.

HTTP-режим

WAZAP_READ_TOKEN=$(openssl rand -hex 32) \
WAZAP_WRITE_TOKEN=$(openssl rand -hex 32) \
npx wazap-mcp serve --http --host 0.0.0.0 --port 8766

Streamable HTTP на /mcp с проверкой работоспособности по /healthz. Два bearer-токена: токен чтения даёт инструменты чтения, токен записи дополнительно разблокирует инструменты записи, так что утёкший токен чтения никогда не сможет никому написать. wazap отказывается привязываться к адресу не-loopback без токена чтения.

Самостоятельный хостинг

Запустите wazap на собственном сервере, когда агент не на вашем ноутбуке: другая машина, VPS, инфраструктура клиента. Сессия остаётся на этом сервере; ничего не проходит через третьи стороны.

С systemd

npm install -g wazap-mcp
sudo useradd --system --home /var/lib/wazap --create-home wazap
sudo -u wazap WAZAP_DATA_DIR=/var/lib/wazap wazap login --phone +15550100   # pairing code works over SSH
sudo -u wazap tee /var/lib/wazap/.env >/dev/null <<END
WAZAP_READ_TOKEN=$(openssl rand -hex 32)
WAZAP_WRITE_TOKEN=$(openssl rand -hex 32)
END
sudo curl -fsSL https://raw.githubusercontent.com/razvangirgiz/wazap/main/deploy/wazap.service -o /etc/systemd/system/wazap.service
sudo systemctl enable --now wazap
curl -s http://127.0.0.1:8766/healthz

Юнит привязывается только к loopback. Поставьте TLS спереди с помощью двухстрочного deploy/Caddyfile (caddy run --config deploy/Caddyfile после редактирования имени хоста) или любого обратного прокси, затем укажите клиенту https://your-host/mcp с Authorization: Bearer <read or write token>.

С Docker

git clone https://github.com/razvangirgiz/wazap && cd wazap
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 wazap-data volume
docker compose up -d
curl -s http://127.0.0.1:8766/healthz

Контейнер публикует 8766 только на loopback; добавьте тот же TLS-прокси спереди. Обновление — это git pull && docker compose up -d --build; том сохраняет сессию.

Какие клиенты могут подключиться

Claude Code, Claude Desktop, Cursor, Codex, VS Code и любой клиент с полем «MCP URL + header» подключаются с bearer-токеном. Connectors в claude.ai требуют OAuth, а не статический токен, поэтому они пока не могут использовать самостоятельный wazap. Держите read-токен в клиентах, которым нужно только читать; выдавайте write-токен осознанно.

Настройки

Переменная

По умолчанию

Значение

WAZAP_DATA_DIR

~/.wazap

Где хранится всё.

WAZAP_READ_ONLY

0

Не регистрировать инструменты записи.

WAZAP_SYNC_FULL_HISTORY

0

Запросить у WhatsApp более полную синхронизацию истории.

WAZAP_PERSIST_HISTORY

1

Сохранять чаты и сообщения между перезапусками.

WAZAP_RATE_LIMIT

20

Вызовы инструментов записи в минуту; 0 отключает.

WAZAP_TRANSPORT

stdio

stdio или http.

WAZAP_HOST / WAZAP_PORT

127.0.0.1 / 8766

Адрес привязки HTTP.

WAZAP_READ_TOKEN / WAZAP_WRITE_TOKEN

не задан

Bearer-токены HTTP.

WAZAP_NO_UPDATE_CHECK

0

1 запрещает status запрашивать у npm новую версию.

Флаги важнее переменных окружения, а те важнее <data-dir>/.env.

Известные ограничения

  • Ключи медиа истекают. WhatsApp удаляет старые вложения со своих серверов, поэтому download_media для старого сообщения возвращает MEDIA_UNAVAILABLE.

  • История — это то, что синхронизирует телефон. wazap видит ту историю, которую WhatsApp передаёт привязанному устройству, а не всю вашу переписку.

  • @lid идентификаторы. WhatsApp адресует собеседников по приватному идентификатору, а не по номеру телефона. wazap переводит их обратно в номера телефонов, когда знает соответствие, и передаёт @lid как есть, когда не знает.

  • Телефон должен оставаться доступным. Привязанное устройство перестаёт получать сообщения, если телефон был офлайн достаточно долго; get_status сообщает об этом.

  • Токен одного устройства. Привязка привязана к одному устройству; повторный вход переносит сессию и разлогинивает предыдущую.

  • @lid не везде. Некоторые поля адресуются по @lid, а не по номеру телефона; wazap преобразует их обратно в номера телефонов, когда узнаёт соответствие.

Разработка

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

npm test не требует подключённого телефона. Smoke-тест stdio запускает собранный бинарник с временным каталогом данных и проверяет, что инструменты перечисляются и get_status работает без привязки.

Лицензия MIT.

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.

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

Output Schema

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

TDQS

A3.6/5.0
Behavior4/5

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

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

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

Conciseness2/5

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

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

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

Completeness4/5

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

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

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

Parameters4/5

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

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

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

Purpose4/5

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

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

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

Usage Guidelines3/5

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

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

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

confirm_sendSend a drafted WhatsApp messageA
Idempotent

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

ParametersJSON Schema
NameRequiredDescriptionDefault
draft_idYesFrom send_message; one with send_at is scheduled, not sent
account_idNoAccount id

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare write/idempotent/non-destructive, so the bar is lower, but the description still adds real value: the once-per-draft guarantee, the 'never redo it unasked' rule, and the outcome-unknown recovery path. It stops short of disclosing auth needs or the concrete response payload, keeping it from 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?

Four dense, front-loaded sentences each carrying distinct actionable content with no filler. The telegraphic fragments ('A yes about something else:', 'Expired, missing or stale:') are efficient but slightly terse to parse.

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 write tool with no output schema, the definition covers the critical edge cases an agent would otherwise mishandle: stale drafts, re-previewing before resend, and the unknown-outcome branch. Little is missing given the annotations already cover the safety profile.

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 100% and both parameters are documented there, including the scheduled-vs-sent nuance on draft_id. The description adds only the loose framing 'this text, this recipient' for what a draft binds, so the baseline 3 applies.

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

Purpose5/5

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

States a specific verb and resource ('Send a draft the user approved') with the exact scope ('this text, this recipient') and explicitly claims exclusivity ('the only call that sends, once per draft'), which separates it from send_message and scheduled_messages. An agent can identify the tool's role 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?

Gives explicit when-to-use (user approved this draft), when-not ('A yes about something else: show the preview again and ask'), and recovery paths for expired/missing/stale drafts plus the SEND_OUTCOME_UNKNOWN branch pointing to read_messages. Alternatives and preconditions are named rather than inferred.

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

delete_messageDelete a WhatsApp messageA
DestructiveIdempotent

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

ParametersJSON Schema
NameRequiredDescriptionDefault
account_idNoAccount id
message_idYes
for_everyoneYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
account_idYes
message_idYes
for_everyoneYes

TDQS

A4.4/5.0
Behavior5/5

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

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

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

Conciseness5/5

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

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

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

Completeness4/5

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

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

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

Parameters3/5

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

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

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

Purpose5/5

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

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

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

Usage Guidelines4/5

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

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

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

edit_messageEdit a WhatsApp message you sentA
DestructiveIdempotent

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

ParametersJSON Schema
NameRequiredDescriptionDefault
textYes
account_idNoAccount id
message_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
textYes
chat_idYes
timestampYes
account_idYes
message_idYes

TDQS

A4/5.0
Behavior3/5

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

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

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

Conciseness5/5

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

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

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

Completeness4/5

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

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

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

Parameters3/5

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

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

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

Purpose5/5

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

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

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

Usage Guidelines4/5

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

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

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

find_contactFind who the user meansA
Read-onlyIdempotent

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

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

Output Schema

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

TDQS

A4.3/5.0
Behavior5/5

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

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

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

Conciseness4/5

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

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

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

Completeness4/5

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

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

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

Parameters3/5

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

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

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

Purpose5/5

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

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

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

Usage Guidelines4/5

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

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

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

get_group_infoGet WhatsApp group infoA
Read-onlyIdempotent

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

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

Output Schema

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

TDQS

A4.5/5.0
Behavior4/5

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

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

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

Conciseness5/5

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

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

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

Completeness5/5

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

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

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

Parameters3/5

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

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

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

Purpose5/5

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

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

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

Usage Guidelines5/5

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

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

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

get_mediaGet the media of a WhatsApp messageC
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.

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

Output Schema

ParametersJSON Schema
NameRequiredDescription
mimeNo
pathNo
sizeNo
typeYes
senderYes
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

C2.3/5.0
Behavior1/5

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

Annotations declare readOnlyHint=true, meaning the tool should not modify its environment. The description explicitly says files can be saved to disk via save_to ('any file saved at path on the machine running wazap') and that transcripts are created and billed ('kept once made; an API provider bills it'), which are environment-modifying side effects. This directly contradicts the readOnlyHint annotation. Although the description does add useful error context (MEDIA_UNAVAILABLE), the contradiction forces a score of 1.

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

Conciseness2/5

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

The description is a dense, run-on sentence with semicolons that reads like internal shorthand rather than structured documentation. It is not front-loaded with a clear purpose statement, and the parenthetical asides make it hard to parse. While not excessively long, its structure impedes quick comprehension.

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?

The tool has an output schema, so return values need not be described. The description covers some behavioral details (transcript caching/billing, save_to effects, MEDIA_UNAVAILABLE error), but it is incomplete for a 4-parameter tool with no usage guidance, and its behavioral claims conflict with the readOnlyHint annotation. It leaves key questions unanswered, such as account_id semantics and whether saving files affects the annotation contract.

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

Parameters3/5

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

Schema description coverage is 75%, so the schema already documents most parameters (save_to, language, account_id). The description adds marginal behavioral context for save_to ('its file, and no new transcript') and indirectly for language (transcript generation), but does not explain message_id or account_id. With high schema coverage, baseline 3 is appropriate.

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

Purpose3/5

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

The description conveys that the tool returns media content (transcripts, files, images) for a message, but it does so in a convoluted, note-like way rather than stating a clear verb+resource. The title supplies the missing 'Get the media of a WhatsApp message' framing, yet the description does not explicitly differentiate this from sibling tools like get_message or read_messages.

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

Usage Guidelines2/5

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

There is no explicit guidance on when to use this tool versus alternatives. The description implies usage (when a message has media) but never states conditions, prerequisites, or when to prefer get_message/read_messages instead. An agent must infer that this is the media-retrieval counterpart to text retrieval.

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
account_idNoAccount id
message_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
textYes
chat_idYes
timestampYes
account_idYes
message_idYes

TDQS

A3.5/5.0
Behavior4/5

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

Annotations already establish read-only, idempotent, non-destructive, open-world behavior, and the description goes beyond them by disclosing the cross-account lookup fallback when account_id is absent and by characterizing the rich payload returned. It omits any mention of permissions, rate limits, or cost of that multi-account scan, keeping it from 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.

Conciseness3/5

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

It is a single long, dense sentence, front-loaded with the core claim 'One message in full,' which is good. However, much of the enumeration (reactions, poll votes, media, read receipts) restates what the output schema already provides, so several clauses do not fully earn their place.

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

Completeness3/5

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

With annotations covering the safety profile and an output schema covering return values, the return-content enumeration is largely redundant and the real gaps remain: no guidance on when to use this versus read_messages or search. The account_id fallback is the one piece of essential context supplied.

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%: account_id has a bare 'Account id' string while message_id is undocumented. The sentence 'Without account_id the id is looked for on every account' genuinely adds semantics for account_id, but message_id (the only required param) gets nothing beyond the schema, so 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 resource is unambiguous ('one WhatsApp message in full') and the description enumerates exactly what 'in full' means: quoted message, reactions with authors, poll votes, media, and read receipts. The verb is only implied (the name/title supply 'get'), and no sibling such as search or read_messages is named to sharpen the distinction, so it lands short of 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?

Usage is implied rather than stated: an agent can infer 'call this when you have a specific message_id and need the complete message.' The one real guideline is the account_id fallback ('the id is looked for on every account'), but there is no when-not-to-use or pointer to alternative retrieval tools.

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

get_statusGet the WhatsApp connection statusA
Read-onlyIdempotent

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

ParametersJSON Schema
NameRequiredDescriptionDefault
account_idNoAccount id
include_pictureNoAdd picture_url, the account's own profile photo (the link expires)

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive/closed-world, so the safety profile is covered. The description adds real behavioral context beyond them: it enumerates the diagnostic fields returned (sudo state codes, sync progress, history freshness, webhook delivery, versions) and notes that accounts includes the default.

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 — it leads with what the tool reveals, then the trigger states. It reads as a stack of fragments and the trailing ellipsis in 'linking with its pairing code…' is sloppy, but every 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 carries the burden of explaining the return payload and does so reasonably: state, sync, history freshness, webhook status, versions, accounts. It omits response structure and whether account_id defaults to the default account, but the essentials for calling and interpreting it are present.

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

Parameters3/5

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

Schema description coverage is 100% and both parameters (account_id, include_picture with its link-expiry note) are documented in the schema itself. The description adds no parameter semantics beyond the structured fields, so the baseline 3 applies.

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 resource and enumerates exactly what the status covers: connection state, sync, history freshness, webhook delivery, versions, and the accounts list. No sibling tool in the set overlaps with this, so explicit differentiation is unnecessary, though no sibling is named either.

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 trigger condition: 'Call it on NOT_CONNECTED, NOT_LINKED or SYNC_IN_PROGRESS.' That is clear when-to-call guidance tied to concrete state names, but it names no alternative tool or when-not-to-call scenario.

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

learnLearn how to use the WhatsApp toolsA
Read-onlyIdempotent

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

ParametersJSON Schema
NameRequiredDescriptionDefault
account_idNoAccount id

TDQS

A4.7/5.0
Behavior4/5

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

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

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

Conciseness5/5

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

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

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

Completeness5/5

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

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

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

Parameters4/5

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

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

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

Purpose5/5

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

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

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

Usage Guidelines5/5

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

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

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

list_chatsList WhatsApp chatsA
Read-onlyIdempotent

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

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
cursorNoOpaque next_cursor from the preceding page; keep the same filter
filterNo"all" leaves out archivedall
account_idNoAccount id
include_picturesNoAdd picture_url, each chat's profile photo (links expire)

Output Schema

ParametersJSON Schema
NameRequiredDescription
syncYes
chatsYes
countYes
filterYes
account_idYes
next_cursorNo

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, non-destructive and openWorld, so the safety profile is covered. The description adds one genuinely new behavioral fact — that results are ordered most-recently-active-first — but omits pagination behavior, and its field inventory duplicates the output schema. One added trait over the annotations lands it at 3.

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 with the resource and ordering front-loaded and no filler. The field inventory is mildly redundant given the output schema exists, but it is short enough that nothing dominates.

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 description needn't explain return values, and annotations cover the safety profile; purpose, usage and ordering are all stated. Only minor gaps remain (no mention of pagination or the filter option), so it is close to complete for a 5-param list tool.

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

Parameters3/5

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

Schema description coverage is 80% (cursor, filter and include_pictures are documented), so the schema carries the parameter burden. The description mentions archiving only in passing ('whether archived') and never explains limit, cursor paging, or the filter enum, so it adds no meaning beyond the schema — the baseline 3 for high coverage.

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 enumerates conversations and names the identifying fields (chat_id, name, type, unread count, last message, state flags). The verb is implied rather than stated ('Conversations...'), and it doesn't explicitly distinguish itself from the sibling list_contacts, but an agent can tell it retrieves chats, not contacts.

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?

'Use it to find a chat_id' gives a concrete reason to reach for this tool, which is the main entry point before message-level tools. It stops short of naming exclusions or alternatives (e.g. search, list_contacts, read_messages) when a chat_id is already known, which keeps it from a 5.

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.

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

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, open-world, so the safety profile is covered. The description goes beyond them by disclosing filtering behavior ('No message words; #private people left out') and an edge case ('address_book_synced false: not arrived yet'), which materially inform result contents.

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?

Purpose and returned fields are front-loaded in the first sentence, with filtering and the sync caveat appended tersely. The fragmentary phrasing ('address_book_synced false: not arrived yet') is dense but earns its place as an edge-case note; no redundant sentences.

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

Completeness4/5

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

With no output schema, the description usefully explains what each row contains and the privacy/status caveats, which is the key missing structured information. Minor gaps remain around account_id acquisition and ordering semantics, but the core call-and-interpret picture is complete.

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

Parameters3/5

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

Schema coverage is 75%, with order and cursor carrying their own descriptions, so the schema does most of the work. The description only loosely reinforces account scoping ('one account') and pagination ('a page at a time') and adds no format or default detail for limit/order beyond the schema, so a 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?

Specific verb (list) and resource (the phone's address book / contacts), and it enumerates the returned fields (name, phone, chat_id, contact_id, last DM time and direction), which makes the resource unambiguous. It does not explicitly name or contrast with siblings such as find_contact or list_chats, so it stops short of 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?

'a page at a time' implies paginated browsing and 'on one account' implies account scoping, so usage is inferable. However, there is no explicit when-to-use / when-not-to-use guidance versus find_contact (lookup) or list_chats, leaving the agent to infer routing.

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

manage_chatManage a WhatsApp chatA
Destructive

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

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

TDQS

A3.9/5.0
Behavior4/5

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

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

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

Conciseness4/5

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

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

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

Completeness4/5

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

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

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

Parameters3/5

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

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

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

Purpose4/5

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

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

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

Usage Guidelines4/5

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

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

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

manage_groupManage a WhatsApp groupA
Destructive

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

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

Output Schema

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

TDQS

A4.6/5.0
Behavior5/5

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

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

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

Conciseness5/5

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

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

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

Completeness4/5

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

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

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

Parameters4/5

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

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

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

Purpose5/5

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

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

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

Usage Guidelines4/5

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

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

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

react_to_messageReact to a WhatsApp messageA
Idempotent

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

ParametersJSON Schema
NameRequiredDescriptionDefault
emojiYes
account_idNoAccount id
message_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
emojiYes
account_idYes
message_idYes

TDQS

A3.8/5.0
Behavior3/5

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

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

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

Conciseness5/5

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

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

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

Completeness4/5

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

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

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

Parameters3/5

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

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

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

Purpose5/5

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

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

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

Usage Guidelines3/5

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

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

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

read_messagesRead messages from a WhatsApp chatA
Read-onlyIdempotent

Read one chat, oldest to newest: the latest messages, or older ones with before (wazap asks the phone when the local history runs out). 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.

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

Output Schema

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

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already cover read-only/idempotent safety, so the bar is lower, yet the description adds real behavioral context: backfilling from the phone when local history runs out, truncation of long texts unless full_text, and that stories appear nowhere else. Default limit and account scoping are left to the schema.

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 but front-loaded: read scope first, then pagination, then the status special case. The parenthetical about wazap asking the phone is slightly digressive but earns its place by explaining an observable latency/backfill behavior.

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?

An output schema exists, so return values need not be described, and annotations cover the safety profile. The description adequately covers the tool's oddities (status mode, backfill, truncation) for an 8-param reader, though it omits the default limit of 20 and the types/limit interaction wording.

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 88%, so the baseline is 3, but the description adds genuinely new meaning: the fallback behavior of 'before', the 'status' value for chat_id and its hours window, and the full_text truncation toggle. Only limit/account_id add nothing beyond the schema.

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

Purpose4/5

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

Specific verb+resource ('Read one chat') with ordering and scope stated up front ('oldest to newest'), which tells an agent this is a single-chat reader rather than a global search. Sibling differentiation is implicit (no sibling named) but the 'chat_id "status"' carve-out usefully separates it from get_status/stories semantics.

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?

Gives pagination context ('or older ones with before') and hints at the status mode ('from the last hours, at most a day'), but never says when to prefer this over get_message, search, catch_up, or list_chats. Usage is implied rather than stated.

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

rememberRemember something about a personA
Idempotent

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

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

Output Schema

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

TDQS

A3.8/5.0
Behavior4/5

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

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

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

Conciseness4/5

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

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

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

Completeness4/5

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

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

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

Parameters4/5

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

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

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

Purpose4/5

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

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

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

Usage Guidelines3/5

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

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

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

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.

ParametersJSON Schema
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_idNoAccount id
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

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

TDQS

A4/5.0
Behavior4/5

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

Annotations only declare the generic safety profile (not read-only, not idempotent, not destructive, closed-world). The description adds real behavior beyond that: reminders are stored locally and delivered to the user's webhook when due, the no_reply condition is skipped if someone replied, and nothing is sent to WhatsApp. Storage/delivery semantics are exactly the kind of context annotations cannot carry.

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 identity is front-loaded in the first clause, then it moves through create, condition, and the list/cancel actions with no filler. The telegraphic fragments ('list, cancel.') and stacked parentheticals are dense but every element carries information for an 11-parameter multi-action tool.

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 no explanation, and the description still covers all three actions, storage location, delivery mechanism, the condition enum, and the no-WhatsApp guarantee. Only minor gaps remain, such as whether list scopes by account_id and what cancel does to already-fired reminders.

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 82%, so the baseline is 3, but the description adds meaning the schema does not encode: after_hours and due_at are alternatives for the same due time, and condition=no_reply means the reminder is suppressed if someone wrote after it was set. It also clarifies reminder_id comes from create or list.

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), the lifecycle operations (create/list/cancel), and the three create inputs, so an agent knows exactly what this tool manipulates. The closing line 'Nothing goes to WhatsApp' implicitly separates it from messaging siblings like scheduled_messages, though it never names that sibling outright.

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 clear per-action context: create takes chat_id, note and either after_hours or due_at; the no_reply condition fires only if nobody wrote since; list and cancel are named. The 'Nothing goes to WhatsApp' clause signals when not to expect messaging behavior, but no alternative tool is named explicitly, so this stops 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.

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.

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

Output Schema

ParametersJSON 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?

Annotations already declare readOnlyHint=false, idempotentHint=true, destructiveHint=false, so the safe/idempotent profile is covered. The description adds genuine context beyond that: list ordering (waiting soonest first, then the week's sent/missed/failed/cancelled) and the recency window, plus an explicit directive to surface missed/failed messages. It stops short of stating permission requirements or what happens if the cancel window has passed.

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-load the primary action, and the closing instruction ('Tell the user about every missed or failed one') is a behavioral requirement an agent genuinely needs. No filler or restatement of the title.

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 adequately covers both the list and cancel branches of the enum action. Minor gaps remain around the limit parameter and error behavior for a cancel attempted too late, but nothing essential to correct invocation is missing.

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

Parameters3/5

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

Schema coverage is 60%, and the description reinforces schedule_id's origin (from the list or confirm_send) and the meaning of the closed-message set, which matches the schema's own include_closed description. The limit parameter (default 50, max 100) is never mentioned, so the description does not fully compensate for the coverage gap. Baseline 3 is appropriate when the schema carries most parameter meaning.

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 resource (the account's scheduled messages) and two concrete verbs (list, cancel), and it explicitly distinguishes itself from the sibling tools send_message and confirm_send that handle scheduling. An agent can identify this tool's role without inspecting 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?

It names the alternative workflow for scheduling (send_message with send_at, then confirm_send) and the condition that selects it, plus the constraint that cancellation must happen 'before it goes.' Use vs. alternative is unambiguous.

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

send_messageDraft a WhatsApp messageA

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

ParametersJSON Schema
NameRequiredDescriptionDefault
asNoMedia: a plain document, a voice note, a looping GIF
urlNoMedia: public http(s) URL
textYesThe message, or the caption, poll question or place name; "" for a forward, a voice note or audio
addressNoLocation: shown under the name
chat_idYesChat id, or a phone number
forwardNoForward this message; text ""
optionsNoPoll answers
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_idNoAccount id
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?

Annotations already declare this as a non-destructive write (readOnlyHint=false, destructiveHint=false), so the safety profile is covered; the description adds the genuinely behavioral facts that nothing is sent, that it returns draft_id and preview, and that a confirmation gate exists. It stops short of disclosing draft persistence/expiry or auth requirements, 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.

Conciseness5/5

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

Roughly two-and-a-half sentences with zero waste: the draft/send distinction and the required inputs lead, and the confirm protocol follows. Every clause carries operational weight, and the preview-then-confirm flow is front-loaded where an agent needs 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 16-parameter tool with no output schema, the description correctly compensates by explaining what comes back (draft_id, preview contents) and how the two-phase draft/confirm workflow proceeds. The remaining parameter surface (send_at, time_zone, mention_ids, account_id) is documented in the schema, though the description never signals scheduling or mentions at all.

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

Parameters3/5

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

Schema description coverage is high at 81%, so the schema already carries most parameter meaning; the description's mention of media, polls, locations and forwards loosely maps to the as/options/latitude/forward groups but adds no syntax or format detail. It reinforces the required recipient+text pair but does not go beyond the structured fields.

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

Purpose5/5

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

States a specific verb (drafts) plus the full range of content it can produce (text, media, polls, locations, forwards) and immediately resolves the name's ambiguity with "sends nothing." It distinguishes itself from confirm_send, which is the sibling that actually sends, so an agent can tell the two apart 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 explicit routing to the alternative ("confirm_send only on a yes to this text and recipient"), including an edge case that a send in the same request counts as that yes. Nothing about when versus when-not is left 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.

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

Output Schema

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

TDQS

A4.8/5.0
Behavior5/5

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

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

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

Conciseness5/5

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

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

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

Completeness5/5

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

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

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

Parameters5/5

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

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

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

Purpose5/5

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

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

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

Usage Guidelines4/5

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

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

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

Tool Schema Changelog

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

  1. 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"
        +  ]
        +}
  2. 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"
        +}
  3. 1 tool updatev1.2.0
    • Addedlist_contacts
  4. 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"
        +}
  5. 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
  6. 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
  7. 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
  8. 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

B3.4/5.0

Scored across 23 tools

Disambiguation4/5

Most tools target a distinct action (send_message vs confirm_send vs edit_message clearly separated; find_contact vs list_contacts distinct). The message-reading cluster (read_messages, get_message, search, catch_up, wait_for_messages) risks overlap, but the very detailed descriptions draw clear boundaries. One or two could still be confused at a glance.

Naming Consistency3/5

Casing is uniformly snake_case, which is good, but the verb_noun pattern is not maintained: get_/list_/read_/manage_/find_ sit alongside bare nouns and verbs (learn, reminder, remember, search, catch_up, scheduled_messages, wait_for_messages). Readable overall, but the verb choice for reading tools (get_status, list_chats, read_messages) is inconsistent.

Tool Count3/5

23 tools is on the heavy side for an agent surface and lands in the 16-25 range. The WhatsApp domain is genuinely broad (messages, chats, groups, contacts, media, scheduling, reminders, status), so each tool is defensible, but the set is large enough that navigation costs are real.

Completeness4/5

Coverage is strong: linking, status, read/search/get, draft-confirm send lifecycle, edit, delete, react, chat and group administration, contacts, media, scheduling, reminders, memory and catch-up are all present. Only minor gaps remain (e.g. no dedicated forward/poll-creation tool, though both are folded into send_message).

Maintenance

ActivityActive
ResponsivenessSlow

Related MCP Connectors

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

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

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

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

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    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.
    25
    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.
    6 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A native MCP server for SocialMate that gives your AI a WhatsApp, enabling it to send and read messages, manage contacts and groups, and more through 44 tools.
    16 npm
    1
    MIT