Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

io.github.razvangirgiz/wazap

NPM · WAZAP-MCP · SCANNED SEP 20

WhatsApp for your agent: chats, messages, media, contacts and groups behind MCP tools.

Available components

+15 this week 94 Trust /100
Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security98
  • No malware found by supply-chain analysis.Pass
  • No known CVEs affecting this package version or its production dependencies.Pass
  • No install/post-install scripts declared.Pass
  • 83 of 268 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency97
  • Source repository is publicly reachable at the declared URL. View diagnostics → Pass
  • Cryptographically verified build provenance (signed, bound to razvangirgiz/wazap). View diagnostics → Pass
  • Clear OSI-approved license (MIT).Pass
  • Actively maintained (last published 3 days ago).Pass
  • Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability79
  • 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 9733 tokens (~256/item across 38 items; 38 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management91
  • Stability check failed: the tool surface changed between 0.10.0 and 0.23.1: 0 tool removals, 1 breaking changes, 14 additions. See how to fix → Fail
Tool Coverage100
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 100% of tool parameters carry a description.Pass
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • All 7 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
  • An AI judge read all 39 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Install

How do I install the io.github.razvangirgiz/wazap MCP server?

io.github.razvangirgiz/wazap runs locally as an npm package, launched with npx -y wazap-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

npm · wazap-mcp

# add to Claude Code
claude mcp add razvangirgiz-wazap -- npx -y wazap-mcp
// .cursor/mcp.json
{
  "mcpServers": {
    "razvangirgiz-wazap": {
      "command": "npx",
      "args": [
        "-y",
        "wazap-mcp"
      ]
    }
  }
}
// .vscode/mcp.json
{
  "servers": {
    "razvangirgiz-wazap": {
      "command": "npx",
      "args": [
        "-y",
        "wazap-mcp"
      ]
    }
  }
}
# add to Codex CLI
codex mcp add razvangirgiz-wazap -- npx -y wazap-mcp
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "razvangirgiz-wazap": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "wazap-mcp"
      ],
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add razvangirgiz-wazap --command npx --arg -y --arg wazap-mcp
# ~/.hermes/config.yaml
mcp_servers:
  razvangirgiz-wazap:
    command: "npx"
    args: ["-y", "wazap-mcp"]
// ~/.netclaw/config/netclaw.json
{
  "McpServers": {
    "razvangirgiz-wazap": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "wazap-mcp"
      ]
    }
  }
}
# add to Vellum
assistant mcp add razvangirgiz-wazap -t stdio -c npx -a -y wazap-mcp
// mcp.json
{
  "mcpServers": {
    "razvangirgiz-wazap": {
      "command": "npx",
      "args": [
        "-y",
        "wazap-mcp"
      ]
    }
  }
}
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 20 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 88 to 91.

  • 18 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 81 to 85.

  • 17 Sept 26 0
    • Stability: fail → unverified security
    • Known CVEs: pass → unverified security
    • Tool safety: pass → unverified security
    • Capabilities: pass → unverified functional
    • Dependency health: 0.85 → unverified functional
    • Tool coverage: 100 → unverified functional
    • Schema quality: 100 → unverified functional
    • Package version: 0.22.0 → 0.23.1 functional
    • Package version: 0.22.0 → 0.23.0 functional
  • 16 Sept 26 +26
    • Stability: fail → unverified security
    • Tool safety: pass → unverified security
    • CVE-2026-82417 no longer affects this package security
    • CVE-2026-82562 no longer affects this package security
    • Malware scan: unverified → pass security
    • Known CVEs: unverified → pass security
    • Capabilities: pass → unverified functional
    • Tool coverage: 100 → unverified functional
    • Schema quality: 100 → unverified functional
    • Dependency health: unverified → 0.85 functional
    • Package version: 0.20.2 → 0.22.0 functional
    • Package version: 0.20.2 → 0.21.0 functional
  • 15 Sept 26 −14
    • Known CVEs: fail → unverified security
    • Malware scan: pass → unverified security
    • Stability: 0.73 → fail security
    • CVE-2026-82562 no longer affects this package security
    • CVE-2026-82417 no longer affects this package security
    • Provenance: fail → pass security
    • Known CVEs: fail → pass security
    • The attested source repository moved: razvangirgiz/wazap security
    • Schema quality: 113 → 248 functional
    • Schema quality: 113 → 228 functional
    • Schema quality: 113 → 227 functional
    • Dependency health: 0.84 → unverified functional
    • First check of Schema quality: 100 functional
    • Package version: 0.10.0 → 0.20.2 functional
    • Package version: 0.10.0 → 0.20.1 functional
    • Package version: 0.10.0 → 0.20.0 functional
    • Package version: 0.10.0 → 0.19.1 functional
    • Package version: 0.10.0 → 0.18.6 functional
  • 14 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 70 to 73. That category is still filling its 30-day observation window: 21 days of observed history at the previous scan, 22 at this one. The score rises as the window fills, whether or not the server changes.

  • 12 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 63 to 67. That category is still filling its 30-day observation window: 19 days of observed history at the previous scan, 20 at this one. The score rises as the window fills, whether or not the server changes.

  • 10 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 57 to 60. That category is still filling its 30-day observation window: 17 days of observed history at the previous scan, 18 at this one. The score rises as the window fills, whether or not the server changes.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 20 Sept 2026 · Analysed npm/wazap-mcp@0.23.1

Provenance Verified

A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.

Result Verified
Ecosystem npm
Reason Verified
Discovered via Registry attestation endpoint
Source repo razvangirgiz/wazap
Certificate issuer https://token.actions.githubusercontent.com
Certificate SAN https://github.com/razvangirgiz/wazap/.github/workflows/publish.yml@refs/tags/v0.23.1
Rekor log index 2872280605
Predicate type https://slsa.dev/provenance/v1
Subject digest sha512:edef4ddff64c3a2c47c2098125efc34078cd8788e62d2ecc131d77911da02eb91b4f3a0d59caf68db0b3775efec1da562544ee6bb3bda02befe580c2b

Background: How many MCP packages publish verified provenance →

Dependencies 268 packages
Packages resolved 268
Stale 83
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 38 exposed · ~9,345 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
confirm_send ~199

Send a draft created by send_message, send_media, send_poll, send_location or forward_message. This is the only call that reaches WhatsApp, and it sends a draft at most once: confirming it again answers the same receipt with already_sent: true. Only the MCP session that created the draft may confirm it. After reinitializing or reconnecting with a new session, draft again and obtain fresh user approval. A missing or expired draft_id also means draft again and show the new preview before calling this. SEND_OUTCOME_UNKNOWN means WhatsApp may have the message: check the chat with read_messages before anything else, and never draft it again without asking the user.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
draft_idstringyesThe draft_id returned by a send_* tool

No output schema declared.

No examples provided.

create_group ~112

Create a group with the given name and participants; the linked account becomes the owner. Each participant comes back with a status: ok, invite_needed (their privacy settings require an invite link) or failed.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
namestringyesGroup name
participant_idsarrayyesChat ids or phone numbers to add (1-256)

No output schema declared.

No examples provided.

delete_message ~243

Delete a message. DESTRUCTIVE — confirm with the user first. for_everyone is required, and picks one of two different deletes; tell the user which: - for_everyone: true retracts it for everyone in the chat. Works on messages the linked account sent, within 2 days of sending. In a group where the linked account is an admin it also takes someone else's message, deleted as an admin; anywhere else that is NOT_OWN_MESSAGE. - for_everyone: false removes it from the linked account's own devices only: anyone's message, at any age. Nobody else sees a change.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
for_everyonebooleanyesRequired. true retracts it for everyone in the chat; false deletes it for the linked account only
message_idstringyesMessage id from read_messages / search_messages / get_message, e.g. "false_4072...@s.whatsapp.net_3EB0..."

No output schema declared.

No examples provided.

download_media ~384

Download the photo/video/audio/document attached to a message and save it to disk on the machine running wazap. The file at `path` is already decrypted — open or process it as is; nothing else is needed. Images of 1 MB or less are also returned inline so you can look at them. The structured result carries: `path` (the saved file), `mime`, `size` (bytes), `filename` (the name it was saved under — a timestamped name wazap made, not the sender's), `original_filename` (the name the sender's file had, or null when the envelope carried none), `caption` (the text the sender wrote under the media, or null — audio and voice notes cannot carry one), `message_id` and `sender` (the same identity fields as search_messages — is_saved, contact_name, pushname, name_source — or null when even the message can no longer be read back). The id resolves in its raw form too: `false_<lid>@lid_<stanza>` works whether or not the chat's number was ever learned — when it was, the lid spelling finds the same message filed under the paired number. An unresolved sender never blocks the file. Without `account_id` the same lookup walks every linked account's store in turn before failing, and the result's `account_id` names the one that served the file. Fails with MEDIA_UNAVAILABLE when WhatsApp has expired the file.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
message_idstringyesA message with has_media=true
save_tostringAbsolute directory to save into (default: <data-dir>/media)

No output schema declared.

No examples provided.

edit_message ~96

Replace the text of a message the linked account sent. WhatsApp only allows this within 15 minutes of sending; after that send a correction instead.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
message_idstringyesA message the linked account sent
textstringyesThe replacement text

No output schema declared.

No examples provided.

forward_message ~131

Draft a forward of an existing message to another chat. Does not send. The recipient will see it marked as forwarded. Show the preview; after the user says yes, call confirm_send.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
message_idstringyesMessage id from read_messages / search_messages / get_message, e.g. "false_4072...@s.whatsapp.net_3EB0..."
to_chat_idstringyesDestination chat

No output schema declared.

No examples provided.

get_contact ~148

Full details for one contact: name, number, about text, profile picture URL, whether they are a saved contact, a business, or blocked. `name_source` says where the shown name comes from — "contact" when it is the saved address-book name (is_my_contact), "pushname" when it is a name the person publishes, or "none" when there is no usable name.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
contact_idstringyesContact id from search_contacts / list_chats, or a phone number

No output schema declared.

No examples provided.

get_group_info ~198

Details of a group: name, description, owner, creation date, whether only admins may post, whether the linked account is an admin, and the participant list (up to 500; participant_count is always the true total). The invite link is included only when the linked account is an admin. The settings come too: info_locked (only admins edit the name, description and photo), member_add_mode ("admins" or "all"), join_approval, disappearing_seconds (0 when off), and community ({is_community, parent_group_id}) when the group is a community or belongs to one. Call this before manage_group: most group actions need admin rights.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
group_idstringyesGroup chat id ("<id>@g.us")

No output schema declared.

No examples provided.

get_message ~472

The complete message behind a message_id, including the quoted message it replies to, each reaction with who left it, who chose each option of a poll or answered an event, and its media metadata. Use it after search_messages or read_messages when you need the context around a single message. On the user's own messages, `delivery.status` says how far it got ("sent", "delivered", "read", "played", "pending" or "error"), and in a group `read_by` and `delivered_to` name who, with the time. It stops at "delivered" or is missing when read receipts are off on either side, and large groups may send none. The id also resolves in its raw form: `false_<lid>@lid_<stanza>` works even when the chat's number was never learned, and an id that names the same message under the lid or the paired number finds it either way. With several accounts linked and no `account_id`, an id the resolved account cannot find is tried on each of the others in turn before MESSAGE_NOT_FOUND comes back, and the answer's `account_id` names the one that had it; pass `account_id` to keep the lookup on one account. The `sender` carries the same identity fields as search_messages: `id` (the canonical jid — a `…@lid` only while WhatsApp has never revealed the paired number), `phone` (the number, or null for an unresolved lid), `is_saved` (whether the sender is in the user's address book), `contact_name` (the name saved there, or null), `pushname` (the name the sender publishes, when that is the name `name` shows) and `name_source` ("contact", "pushname" or "none" — which of those `name` came from).

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
message_idstringyesMessage id from read_messages / search_messages / get_message, e.g. "false_4072...@s.whatsapp.net_3EB0..."

No output schema declared.

No examples provided.

get_recent_messages ~343

Everything that happened recently, grouped by chat. This is the catch-up tool: one call instead of list_chats plus a read_messages per chat. WhatsApp's own notices — device linking, group membership changes, encryption notices — are left out so the counts are conversation; pass include_system to see them. A chat lists at most its newest 2,000 messages of the window.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
compactbooleanLeave 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 c…
filterstringRestrict to unread chats, groups, or one-to-one chats
hoursintegerLook-back window in hours (1-168)
include_previewsbooleanAttach 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…
include_systembooleanInclude WhatsApp's own system notices, which are excluded from the bodies and the counts by default
typesarrayKeep 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.

No output schema declared.

No examples provided.

get_status ~309

Check the session: connection status ("connected" means the tools work, "not_linked" means the user must run `npx wazap-mcp login`), whether the initial history sync has finished, which account is linked, how fresh the local history is — `history` shows when a message last arrived and flags `stale` when the phone has been quiet for a day while connected — the versions and data directory in use, and how many contacts carry a name from the phone's address book (contacts_named: 0 means it never arrived). `webhook.delivery` counts the account's webhook events: delivered (last 7 days), failed and cancelled (last 30), pending; a non-zero `consecutive_failures` or `retrying` means the receiver is refusing or unreachable right now, and `last_failure` says how. Call this whenever another tool reports NOT_CONNECTED, NOT_LINKED or SYNC_IN_PROGRESS, or to confirm which account you are about to send from. Without account_id the top-level fields are the default account, plus `accounts` listing every live one. While a link is in progress the status is "linking" and `pairing` carries the code the user still has to type into their phone.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.

No output schema declared.

No examples provided.

get_stories ~219

The stories (status updates) the linked account has received in the last N hours, newest first, each with its author, its text or caption and its time. WhatsApp keeps a story for a day and so does wazap; nothing older is held. With include_previews the photos come as small images, and download_media works on a story's message_id like on any message. Stories never appear in chats, catch-ups or waits; this is the only place they show.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
hoursintegerLook-back window in hours (1-24)
include_previewsbooleanAttach 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…

No output schema declared.

No examples provided.

get_unanswered ~307

Chats where the last word is theirs and it asks for something: a question, a request ("poți", "te rog", "can you", "when"…), or a voice note nobody has heard yet. A conversation that ended in "ok, thanks" is not listed, and neither is an ask older than max_age_hours (two weeks by default): that one was abandoned, not left waiting. Groups count only when the user was @-mentioned or replied to after their own last message. A [business] account's ask is often an automatic reply; weigh it accordingly. People come first, then the oldest wait. Each entry quotes the ask, says how many of their messages arrived since the user's last one, and how long they have been waiting. This is the follow-up half of an inbox triage; use get_recent_messages for what happened, and this for who is still waiting.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
limitintegerMaximum number of chats (1-50)
max_age_hoursnumberIgnore asks older than this; an ask left for two weeks (the default) is abandoned, not waiting
min_age_hoursnumberOnly asks at least this old, e.g. 48 for people the user forgot for two days

No output schema declared.

No examples provided.

join_group ~239

Join a group from an invite: a link (https://chat.whatsapp.com/<code>, or the code alone) as invite, or the message_id of an invite message someone sent (type "invite"). Exactly one of invite / message_id. Without confirm: true it joins nothing and returns the group's name, description, member count and whether an admin must approve new members. Show that to the user and wait for an explicit yes, then call again with the same invite or message_id and confirm: true. Every member sees the account join. The answer is the group's chat_id, or pending_approval when an admin must let the account in first.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
confirmbooleantrue joins, only after the user said yes to the preview; omit to preview
invitestringA https://chat.whatsapp.com/ link, or its code
message_idstringAn invite message (type "invite") from read_messages

No output schema declared.

No examples provided.

learn ~90

Read this FIRST, before any other WhatsApp tool. Returns the guide to the tools, the id formats, the recommended workflows, the message shape and every error code with what to do about it. Takes no arguments and never touches WhatsApp.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.

No output schema declared.

No examples provided.

link_account ~217

Pair this wazap with the user's WhatsApp when get_status says not_linked, logged_out, session_corrupt or auth_failure. Ask the user for their phone number in international format, call this, and show them the code it returns with these exact steps: WhatsApp → Settings → Linked devices → Link a device → Link with phone number instead → enter the code. Then call get_status every 10 seconds until it says connected (up to 3 minutes). The code expires; call this again for a fresh one if get_status goes back to not_linked with an error. The account must already exist (`wazap account add`). Pass account_id when more than one is configured. An unknown id is ACCOUNT_NOT_FOUND. Never call this when the account is already linked.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
phonestringyesInternational format, e.g. +15550100

No output schema declared.

No examples provided.

list_accounts ~105

List every configured WhatsApp account: id, name, connection status, masked phone, owner name, and whether that account allows writes. Call this first when more than one account is linked, then pass account_id on the other tools. Takes no arguments besides the optional account_id (ignored for the listing).

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.

No output schema declared.

No examples provided.

list_chats ~141

List conversations, most recently active first. Use it to discover the chat_id values the other tools need. Each chat has: chat_id, name, type, unread_count, last_message {text, timestamp, from_me}, archived, pinned, muted_until, and left (groups you are no longer in).

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
filterstringWhich chats to list; "all" (default) excludes archived ones
limitintegerMaximum number of chats (1-100)

No output schema declared.

No examples provided.

manage_chat ~385

Change a chat, or a message in it. Actions: - archive / unarchive, pin / unpin (the chat), mute / unmute (mute_hours defaults to 8), mark_read (sends read receipts) / mark_unread - pin_message / unpin_message — need message_id; pins it for everyone in the chat, for pin_hours 24, 168 (default) or 720 - star_message / unstar_message — need message_id; the star is the linked account's own - clear — DESTRUCTIVE, empties the chat for the linked account only - delete — DESTRUCTIVE, deletes the chat for the linked account only - block / unblock — a person's chat only; a blocked person can no longer message or call the account A message_id must belong to chat_id. Every action hits WhatsApp at once and there is no draft: say what will change and wait for a yes before calling it.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
actionstringyesWhat to do with the chat
chat_idstringyesChat id as returned by another tool ("<digits>@s.whatsapp.net" or "<id>@g.us"), or a phone number in international format
message_idstringThe message for pin_message, unpin_message, star_message and unstar_message; it must be in chat_id
mute_hoursintegerHours to mute, default 8; only used by "mute"
pin_hoursnumberHow long pin_message keeps the message pinned: 24, 168 (default) or 720 hours

No output schema declared.

No examples provided.

manage_group ~501

Administer a group. Actions: - add / remove / promote / demote — need participant_ids; each participant comes back with status ok, invite_needed or failed - leave — DESTRUCTIVE, rejoining needs an invite - set_subject / set_description — need value - set_picture — needs exactly one of file_path / url: JPEG, PNG or WebP, at most 10 MB. Every member sees it at once and there is no draft: show the image and wait for a yes first - remove_picture — takes the group photo down; ask first the same way - get_invite_link / revoke_invite_link - list_join_requests — who is waiting for approval, with when and how they asked - approve_join_requests / reject_join_requests — need participant_ids from list_join_requests; each comes back with status ok or failed - set_announcement_only / set_info_locked / set_join_approval — value "on" or "off" - set_add_mode — value "admins" or "all" - set_disappearing — value "off", "24h", "7d" or "90d" Everything except leave requires the linked account to be a group admin; call get_group_info first to check. Every change is visible to all members at once: say what will change and wait for a yes before calling it.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
actionstringyesGroup action to perform
file_pathstringset_picture: absolute path of a local JPEG, PNG or WebP
group_idstringyesGroup chat id ("<id>@g.us")
participant_idsarrayTargets of add/remove/promote/demote/approve_join_requests/reject_join_requests
urlstringset_picture: public http(s) URL to fetch and use as the photo
valuestringNew 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

No output schema declared.

No examples provided.

mark_handled ~169

The user dealt with what this chat was asking, outside WhatsApp or by a reply wazap did not see: a phone call, a meeting, a decision. The open ask is remembered as handled and the chat leaves get_unanswered. The next message from the other side makes a new ask and the chat comes back on its own. Kept on this machine only; nothing is sent or marked read on WhatsApp.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
chat_idstringyesChat id as returned by another tool ("<digits>@s.whatsapp.net" or "<id>@g.us"), or a phone number in international format

No output schema declared.

No examples provided.

react_to_message ~119

Add an emoji reaction to a message, or pass an empty string to remove your reaction.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
emojistringyesA single emoji such as "👍", or "" to remove your reaction
message_idstringyesMessage id from read_messages / search_messages / get_message, e.g. "false_4072...@s.whatsapp.net_3EB0..."

No output schema declared.

No examples provided.

read_messages ~274

Read messages from one chat, oldest to newest. Without `before` you get the most recent messages. Pass `before` (the oldest message_id you already have) to page further back; wazap asks the phone for older history when the local store runs out, which takes a few seconds.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
beforestringReturn the messages immediately older than this message_id
chat_idstringyesChat id as returned by another tool ("<digits>@s.whatsapp.net" or "<id>@g.us"), or a phone number in international format
include_previewsbooleanAttach 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…
limitintegerMaximum number of messages (1-200)
typesarrayKeep 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.

No output schema declared.

No examples provided.

recall ~637

Search by meaning and by words at once over the whole WhatsApp history — answers "the invoice Dan mentioned", "the address Ana sent", "what did they say about the trip". A paraphrase or another language still hits through its meaning, and a short or foreign-language question still hits through its words; the two rankings are fused. A match found by meaning weighs a little less with age (85% a month on, never under 70%), so the fresher of two close matches comes first but a clearly closer old one still does; one chat takes at most three leading places before other chats' hits, and a near-duplicate trails the list. For an exact string — an id, a phone number, a URL — search_messages is the better tool. Each result carries its date, a fused score, `matched` ("words", "meaning" or "both") and the cosine `similarity` when its meaning ranked it. chat_id, since, until and from narrow the search exactly like search_messages — including a name that resolves to exactly one person. A hit marked "index only" is a message wazap holds only as text: quote its words; get_message returns them, but download_media has nothing to open and it cannot be replied to or forwarded. A hit found only by meaning must clear the similarity floor, so a question with no answer comes back empty; when only weak meaning matches survive, the output says so — do not present them as found facts. When semantic recall is off or its embedding setup is missing, the tool does not dead-end: it falls back to a keyword search over the local history, marked `mode: "keyword_fallback"`, and `recall_unavailable.fix` names the command that turns semantic recall on. An error remains only when even the fallback cannot run. Each hit's `sender` carries the same identity fields as search_messages, and `freshness` says whether the local history may be partial or stale. Every answer also declares its window: the semantic path reports how many messages the index covers, and a keyword fallback carries the same `coverage`…

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
chat_idstringRestrict the search to this chat
fromstringOnly 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)
limitintegerMaximum number of results (1-50)
querystringyesWhat to find, said any way — the meaning is what matches
sincestringOnly messages from this moment on: a date ("2026-09-01") or an ISO timestamp
untilstringOnly messages up to this moment: a date or an ISO timestamp

No output schema declared.

No examples provided.

remove_contact ~97

Take a person out of the account's WhatsApp contacts: the saved entry and its name go, the chat and its history stay. Nothing is sent to the contact.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
contact_idstringyesContact id from search_contacts / get_contact, or a phone number

No output schema declared.

No examples provided.

save_contact ~206

Save a person in the account's WhatsApp contacts: a new entry for a phone number, or a new name for an existing one. The name syncs to every linked device, and with save_on_phone (default) also into the phone's own address book. WhatsApp keeps no other fields — email, "my accountant" and the like go to set_contact_note, which stays on this machine.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
contact_idstringyesContact id from search_contacts / get_contact, or a phone number
first_namestringFirst name, when it differs from the full name
namestringyesFull name to save the contact under
save_on_phonebooleanAlso write the contact into the phone's address book; false keeps it inside WhatsApp

No output schema declared.

No examples provided.

search_contacts ~183

Find contacts by name, phone number, tag or detail: a substring match on the name, a digit match on the number, or a word from a local tag or detail — so "contabil" finds the person filed under role: contabil by update_contact_details. With only tag it lists everyone carrying that tag. Returns contact_id values usable as chat_id.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
limitintegerMaximum number of results (1-50)
querystringName fragment, phone number, or tag/detail text (at least 2 characters). Omit with tag to list everyone carrying it.
tagstringOnly contacts filed under this tag ("client"); "#" optional

No output schema declared.

No examples provided.

search_messages ~685

Substring search over the messages wazap holds locally — all chats, or one chat, including history synced on first link. Case and diacritics are ignored ("sedinta" finds "ședință"). Every message the phone synced to this device is kept and searched; there is no per-chat window. It cannot reach messages the phone never synced to this device. Every answer declares the window it searched: `coverage.searched` counts the held messages in scope (the chat scope and time filters applied) and `coverage.oldest_at`/`newest_at` bound that window, so "no messages found" always says how much history was searched. `coverage.per_chat_cap` is null: no chat is capped. A query so short or so common that the search reaches its scan limit answers `scan_capped: true` and `searched_back_to`: messages older than that were not searched, so narrow it (chat_id, since/until, a longer query) before concluding nothing exists. `from` accepts "me", a phone number, a contact/chat id, or a name: a name must resolve to exactly one person — it matches contact names, notify names and last-seen pushnames, then one-to-one chat display names — or the error lists the candidates it found. Every message's `sender` carries `id` (the canonical jid — a `…@lid` only while WhatsApp has never revealed the paired number), `phone` (the number, or null for an unresolved lid), `is_saved` (the sender is in the user's address book — when false, treat the shown name as claimed, not known), `contact_name` (the name saved there, or null), `pushname` (the name the sender publishes, when that is the name `name` shows; null for saved contacts and unnamed senders) and `name_source` ("contact", "pushname" or "none" — which of those `name` came from). A sender wazap knows nothing about reads "unknown (lid …1234)" — never bare lid digits, which look like a phone number and are not one. `freshness` says whether the history this searched may be partial (sync still running) or stale (nothing inbound for 24h while connected); on…

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
chat_idstringRestrict the search to this chat
fromstringOnly 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)
limitintegerMaximum number of results (1-50)
querystringyesText to search for
sincestringOnly messages from this moment on: a date ("2026-09-01") or an ISO timestamp
untilstringOnly messages up to this moment: a date or an ISO timestamp

No output schema declared.

No examples provided.

send_location ~160

Draft a map pin, optionally labelled with a place name and address. Does not send. Show the preview; after the user says yes, call confirm_send.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
addressstringStreet address shown under the name
chat_idstringyesChat id as returned by another tool ("<digits>@s.whatsapp.net" or "<id>@g.us"), or a phone number in international format
latitudenumberyesLatitude in decimal degrees
longitudenumberyesLongitude in decimal degrees
namestringPlace name shown on the pin

No output schema declared.

No examples provided.

send_media ~286

Draft an image, video, audio file, document or GIF, from a local path on the machine running wazap or from a public URL. Does not send. Exactly one of file_path / url. Maximum 100 MB. Show the preview; after the user says yes, call confirm_send. A GIF is sent with as_gif: an mp4 goes out looping, a .gif is converted to mp4 first (needs ffmpeg on the machine running wazap).

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
as_documentbooleanSend as a plain document instead of rendered media
as_gifbooleanSend a .gif or an mp4 as a looping GIF, the way WhatsApp plays them
as_voicebooleanSend an audio file as a voice note (push-to-talk)
captionstringText shown under the media
chat_idstringyesChat id as returned by another tool ("<digits>@s.whatsapp.net" or "<id>@g.us"), or a phone number in international format
file_pathstringAbsolute path of a local file to send
urlstringPublic http(s) URL to fetch and send

No output schema declared.

No examples provided.

send_message ~247

Draft a text message. Does not send. Returns a draft_id and a preview of the recipient and exact text. Show that preview to the user; after they say yes, call confirm_send. A draft lasts 15 minutes. To @-mention people, pass mention_ids and write @<number> in the text where each mention belongs, the digits of their id (@40722123456). A mention the text lacks gets its @<number> added at the end, so the preview is the text that goes out.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
chat_idstringyesChat id as returned by another tool ("<digits>@s.whatsapp.net" or "<id>@g.us"), or a phone number in international format
mention_idsarrayChat ids to @-mention; write @<number> in the text for each, or wazap adds it at the end
reply_tostringQuote-reply to this message
textstringyesThe message text

No output schema declared.

No examples provided.

send_poll ~171

Draft a poll. Does not send. Participants vote in WhatsApp, and their votes show on the poll message: read_messages counts them and get_message says who chose each option. Show the preview; after the user says yes, call confirm_send.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
chat_idstringyesChat id as returned by another tool ("<digits>@s.whatsapp.net" or "<id>@g.us"), or a phone number in international format
multi_selectbooleanAllow voters to pick more than one option
optionsarrayyesAnswer options (2-12)
questionstringyesThe poll question

No output schema declared.

No examples provided.

set_contact_note ~149

Remember something about a person, on this machine only: "Hermi, my own agent", "the accountant", "always answers late". The note then rides along wherever the contact shows: list_chats, search_contacts, get_contact, get_recent_messages and get_unanswered. Nothing is sent to WhatsApp and the contact never sees it. An empty note removes it.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
contact_idstringyesContact id or phone number
notestringyesWhat to remember, or "" to remove the note

No output schema declared.

No examples provided.

set_profile_picture ~160

Set the linked WhatsApp account's own profile picture from a local path on the machine running wazap or from a public URL. Exactly one of file_path / url. JPEG, PNG or WebP only, at most 10 MB. DESTRUCTIVE and visible to every contact. Show the image and wait for a yes first. This call hits WhatsApp immediately; there is no draft.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
file_pathstringAbsolute path of a local JPEG, PNG or WebP
urlstringPublic http(s) URL to fetch and use as the photo

No output schema declared.

No examples provided.

sync_contacts ~149

Ask WhatsApp to send the linked phone's address book from scratch, and wait up to 15 seconds for it. Nothing on WhatsApp changes: this only refills wazap's own contact list. Use it when get_status reports contacts_named: 0, or when senders in a group read as phone numbers for people you know are saved on the phone. Returns named_before and named_after so you can tell whether it helped; if both are 0 the phone has no saved contacts for these people.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.

No output schema declared.

No examples provided.

transcribe_audio ~260

Turn a voice note or an audio message into text. The transcript is cached, so a second call on the same message costs nothing, and from then on the message reads as [voice message · 0:42] "what was said" in read_messages, get_recent_messages and get_message, and its words become searchable through search_messages. What it costs depends on how the user set transcription up: the local provider (whisper.cpp) is free and the audio never leaves the machine, while the API provider uploads the audio to a third-party service and is billed per minute. Either way this is capped at 10 calls a minute. TRANSCRIBE_UNAVAILABLE means transcription is off or unfinished on this machine; the fix names the command the user has to run. Do not retry it.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
languagestringISO 639-1 code of what is spoken, e.g. "ro"; "auto" detects it. Omit to use the configured default.
message_idstringyesA message whose type is voice or audio

No output schema declared.

No examples provided.

update_contact_details ~262

File local, searchable details on a person: tags like "client" or "echipa", and key-value fields like {"role": "contabil", "oras": "Cluj"}. This is how "the accountant" or "all suppliers" resolve later — search_contacts matches tag and field text, and its tag filter lists everyone carrying one. Nothing is sent to WhatsApp: the contact never sees it and the phone is unchanged. A field set to "" is deleted; remove_tags / remove_fields take keys away. Pass at least one of the four edits. The person need not be a saved contact.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
add_tagsarrayTags to file under, e.g. ["client", "echipa"]; lowercase tokens, "#" optional
contact_idstringyesContact id or phone number
fieldsobjectDetails to set, e.g. {"role": "contabil"}; an empty value deletes the key
remove_fieldsarrayDetail keys to delete
remove_tagsarrayTags to take off

No output schema declared.

No examples provided.

wait_for_messages ~292

Block until a message arrives, then return it, or return empty when the timeout passes. This is how an agent stays on the line without polling: call it in a loop, and pass the cursor it returns into the next call so nothing that landed between two calls is missed. The first matching message starts a one-second settle so a burst comes back together. Only messages from other people are returned, never the user's own, and never WhatsApp's system notices. With addressed_to_me, only direct messages, group messages that @-mention the user, and replies to the user's own messages wake the wait; everything else in a group is ignored. A cursor from a previous run of wazap cannot be honoured: the wait then starts from now and says cursor_reset. The timeout is capped at 55 seconds because MCP clients give up at 60.

NameTypeReqDescription
account_idstringRegistry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.
addressed_to_mebooleanOnly direct messages, @-mentions of the user and replies to the user's messages
chat_idstringOnly messages in this chat
cursorstringThe cursor returned by the previous call
timeout_secondsintegerHow long to wait (1-55 s)

No output schema declared.

No examples provided.

Common questions

What is the io.github.razvangirgiz/wazap MCP server?

io.github.razvangirgiz/wazap is an MCP server listed in the public MCP registry as io.github.razvangirgiz/wazap. WhatsApp for your agent: chats, messages, media, contacts and groups behind MCP tools. This page covers its npm package (wazap-mcp).

Is the io.github.razvangirgiz/wazap MCP server safe to use?

io.github.razvangirgiz/wazap scores 94 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 20 September 2026. It declares no install or post-install scripts. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the io.github.razvangirgiz/wazap MCP server expose?

io.github.razvangirgiz/wazap exposes 38 tools: learn, get_status, list_accounts, link_account, list_chats, and 33 more. Their descriptions and schemas cost roughly 9,345 tokens of context every time the server is loaded.

Is the io.github.razvangirgiz/wazap MCP server still maintained?

io.github.razvangirgiz/wazap is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

What licence is the io.github.razvangirgiz/wazap MCP server under?

io.github.razvangirgiz/wazap declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.