Skip to main content
Glama
DimitrisPasakaleris

WhatsApp MCP Server

WhatsApp MCP Server

CI License: MIT Python 3.11+ Go 1.24+

A Model Context Protocol (MCP) server for WhatsApp, enabling Claude to read and send WhatsApp messages.

Originally created by Luke Harries. Maintained by Very Good Plugins.

Features

  • Message Management: Search and read personal WhatsApp messages (text, images, videos, documents, audio)

  • Contact Search: Search contacts by name or phone number with sender_display format ("Name (phone)")

  • Send Messages: Send text messages to individuals or groups

  • Media Support: Send and download images, videos, documents, and voice messages

  • Call History: Capture incoming voice/video calls into a local SQLite table (live, 1:1 and group)

  • Webhook Integration: Forward incoming messages to external services

  • Local Storage: All messages stored locally in SQLite - only sent to Claude when you allow it

Related MCP server: whatsapp-local-mcp

Installation

Prerequisites

  • Go 1.24+

  • Python 3.11+

  • uv package manager

  • Claude Desktop or Cursor

  • FFmpeg (optional, for voice message conversion)

The Python server currently uses the MCP SDK v1 FastMCP API. The dependency is bounded below v2 so a fresh install does not select an incompatible major release. CI selects its Go toolchain from whatsapp-bridge/go.mod.

Quick Start

  1. Clone the repository

    git clone https://github.com/verygoodplugins/whatsapp-mcp.git
    cd whatsapp-mcp
  2. Start the WhatsApp bridge

    cd whatsapp-bridge
    go run .

    Scan the QR code with WhatsApp on your phone to authenticate.

  3. Configure Claude Desktop

    Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

    {
      "mcpServers": {
        "whatsapp": {
          "command": "whatsapp-mcp"
        }
      }
    }

    The whatsapp-mcp console script is installed by pip install -e . (or pipx install .) from the repo root. If you'd rather not install editable, you can call the module directly:

    {
      "mcpServers": {
        "whatsapp": {
          "command": "python",
          "args": ["-m", "whatsapp_mcp"],
          "cwd": "/path/to/whatsapp-mcp"
        }
      }
    }

    Replace /path/to/whatsapp-mcp with your actual repo path.

  4. Restart Claude Desktop

Updating

Pull the latest changes, then refresh whichever components moved:

git pull

You changed

What to do

Bridge code (whatsapp-bridge/*.go) and you run go run .

Nothing — go run recompiles each launch. Just restart the bridge.

Bridge code and you run a built binary

cd whatsapp-bridge && go build -o whatsapp-bridge && ./whatsapp-bridge

MCP server (src/whatsapp_mcp/*.py, pyproject.toml)

Restart Claude Desktop / Cursor. If you installed with -e, edits are picked up immediately; otherwise re-run pip install -e . to refresh the entry point.

Updates do not require re-pairing or deleting whatsapp.db — your session and message history are preserved. Re-pairing is only needed when explicitly requesting full history (see Requesting full history).

Cursor IDE Configuration

Add to your Cursor MCP settings (~/.cursor/mcp.json):

{
  "mcp": {
    "servers": {
      "whatsapp": {
        "command": "whatsapp-mcp"
      }
    }
  }
}

Tools

Messages include sender_display showing "Name (phone)" format for easy identification by agents.

Contact Operations

search_contacts

Search contacts by name or phone number.

Parameters:

  • query (required): Name or phone number to search

Natural Language Examples:

  • "Find contacts named John"

  • "Search for phone number 555-1234"

  • "Who has the phone number starting with +1?"

get_contact

Resolve a WhatsApp contact name from a phone number, LID, or full JID.

Parameters:

  • identifier (required): Phone number, LID, or full JID (aliases: phone_number, phone)

    • Examples: 12025551234, 184125298348272, 12025551234@s.whatsapp.net, 184125298348272@lid

Natural Language Examples:

  • "What's the name for phone number 5551234567?"

  • "Look up who owns this number"

  • "Who is 184125298348272@lid?"

Message Operations

list_messages

Get messages with filters, date ranges, and sorting.

Parameters:

  • chat_jid (optional): Filter by specific chat JID

  • limit (optional): Number of messages (default 50, max 500)

  • before_date (optional): Messages before this date (YYYY-MM-DD)

  • after_date (optional): Messages after this date (YYYY-MM-DD)

  • sort_by (optional): "newest" or "oldest" (default "newest")

Natural Language Examples:

  • "Show me the last 100 messages from today"

  • "Get messages from the family group chat"

  • "Find messages from last week"

send_message

Send a text message to a contact or group.

Parameters:

  • recipient (required): Phone number or group JID

  • message (required): Text content to send

Natural Language Examples:

  • "Send 'Hello!' to +1234567890"

  • "Message the team group saying 'Meeting at 3pm'"

send_file

Send a media file (image, video, document).

Parameters:

  • recipient (required): Phone number or group JID

  • file_path (required): Path to the file

  • caption (optional): Caption for the media

send_audio_message

Send a voice message (automatically converts to Opus .ogg format).

Parameters:

  • recipient (required): Phone number or group JID

  • file_path (required): Path to audio file

Relative upload paths are resolved by the MCP process before forwarding them to the bridge. Temporary audio conversions are removed after the request; original files are retained. Bridge requests use a 30-second timeout. A send timeout means delivery is unknown, so check the chat before retrying to avoid sending the same message twice.

download_media

Download media from a received message.

Parameters:

  • message_id (required): ID of the message with media

  • chat_jid (required): JID of the chat containing the message

Chat Operations

list_chats

List all chats with metadata.

Parameters:

  • limit (optional): Number of chats (default 50, max 200)

get_chat

Get specific chat metadata by JID.

Parameters:

  • jid (required): Chat JID

get_direct_chat_by_contact

Find a direct message chat with a contact.

Parameters:

  • phone (required): Phone number of the contact

get_contact_chats

List all chats involving a specific contact.

Parameters:

  • phone (required): Phone number of the contact

get_last_interaction

Get the last message exchanged with a contact.

Parameters:

  • phone (required): Phone number of the contact

get_message_context

Get messages around a specific message for context.

Parameters:

  • message_id (required): ID of the target message

  • chat_jid (optional): JID of the chat; required if the message ID occurs in multiple chats

  • before (optional): Number of messages before (default 5)

  • after (optional): Number of messages after (default 5)

Message context preserves the requested sort order and does not collapse equal message IDs from different chats. Chat listings return one row per chat even when several messages share the latest timestamp.

Configuration

Copy .env.example to .env and configure as needed:

Set these variables in the MCP process environment (or load .env through your process manager). A source checkout resolves its default database location to whatsapp-bridge/store, even before first pairing. Explicit WHATSAPP_DB_PATH, WHATSMEOW_DB_PATH, and WHATSAPP_API_URL values override those defaults. Startup probes the configured API's /health route; a disconnected bridge is recognized as running rather than launching another instance.

Variable

Default

Description

WHATSAPP_BRIDGE_PORT

8080

Port for Go bridge REST API

WEBHOOK_URL

http://localhost:8769/whatsapp/webhook

Webhook for incoming messages

FORWARD_SELF

true

Forward messages sent by self

WHATSAPP_DB_PATH

../whatsapp-bridge/store/messages.db

Path to SQLite database

WHATSMEOW_DB_PATH

../whatsapp-bridge/store/whatsapp.db

whatsmeow DB used for LID ↔ phone resolution

WHATSAPP_API_URL

http://localhost:8080/api

Go bridge REST API URL

Set WEBHOOK_URL to an explicitly empty value to disable forwarding. Leaving the variable unset preserves the localhost default. Webhook receivers may return any successful 2xx response, including 201 and 204.

CLI flags (Go bridge)

Flag

Default

Description

--full-history-pair

false

Request full history at pair time. Only takes effect on a fresh pair (no existing whatsapp.db); no-op for already-paired sessions. The phone ultimately decides the actual history window sent — see Requesting full history below.

Requesting full history

whatsmeow's default pairing asks for "recent sync" — roughly the last 3 months, with the exact window decided by the phone. If you want to pull more history at pair time:

# Stop the bridge
launchctl bootout gui/$UID/com.whatsapp-bridge    # or however you manage it

# Back up, then remove the auth session (keeps messages.db intact)
cp whatsapp-bridge/store/whatsapp.db{,.bak}
rm whatsapp-bridge/store/whatsapp.db

# Re-pair with the flag
cd whatsapp-bridge
./whatsapp-bridge --full-history-pair
# Scan the QR with WhatsApp → Settings → Linked Devices → Link a Device
# Wait for "History sync complete" in the logs (can take 10-30 minutes)
# Ctrl+C when sync has quiesced, then restart under your normal process manager

Caveats:

  • The phone decides the actual cap. The flag requests up to 10 years / 100 GB, but WhatsApp's iOS primary device enforces its own retention policy. iPad companion is documented at ~1 year max; other linked devices appear to follow similar logic.

  • Only effective on a fresh pair. With whatsapp.db already present, no new pair handshake fires and the flag is a no-op.

  • Messages the phone has deleted are not recoverable — auto-expire, low-storage cleanup, and manual delete all leave no trace for the phone to share.

Call History

The bridge captures incoming WhatsApp voice and video calls live into a dedicated calls table in messages.db. When a 1:1 call arrives (CallOffer) or a group call is announced (CallOfferNotice), a row is inserted with result='in_progress'. Subsequent CallAccept / CallReject / CallTerminate events update the row — final result becomes answered, rejected, missed, or ended depending on the event sequence. See the state-machine comment above StoreCallOffer in main.go for the exact transitions.

Schema

CREATE TABLE calls (
    call_id TEXT,
    chat_jid TEXT,          -- group JID for group calls, call creator JID for 1:1
    from_jid TEXT,          -- JID of whoever started the call
    timestamp TIMESTAMP,    -- call start time
    is_from_me BOOLEAN,
    call_type TEXT,         -- 'voice' or 'video'
    is_group BOOLEAN,
    result TEXT,            -- 'in_progress' | 'answered' | 'ended' |
                            --   'missed' | 'rejected'
    duration_sec INTEGER,   -- computed when the call terminates
    ended_at TIMESTAMP,
    reason TEXT,            -- terminate reason string from whatsmeow
    PRIMARY KEY (call_id, chat_jid)
);

Caveats

  • Outbound calls are not captured. WhatsApp's primary device handles calls it initiates without notifying linked devices, so the bridge never sees an event for them.

  • Call results only reflect what the bridge saw. If the bridge is offline when a call happens, the events are lost.

  • 1:1 calls default to call_type='voice'. CallOffer events don't expose media type directly (it's buried in the binary call data). Group calls via CallOfferNotice include a Media field and are recorded accurately as voice or video.

Architecture

flowchart TB
    subgraph Clients["AI Clients"]
        CD[Claude Desktop]
        CU[Cursor IDE]
        CC[Claude Code]
    end

    subgraph MCP["MCP Layer"]
        PY[Python MCP Server<br/>FastMCP]
    end

    subgraph Bridge["WhatsApp Bridge"]
        GO[Go Bridge<br/>whatsmeow]
        DB[(SQLite<br/>messages.db)]
        WH[Webhook Handler]
    end

    subgraph External["External Services"]
        WA[WhatsApp Web API]
        EXT[External Webhook<br/>Receiver]
    end

    CD & CU & CC -->|MCP Protocol| PY
    PY -->|REST API| GO
    PY -->|Read| DB
    GO -->|Store| DB
    GO <-->|WebSocket| WA
    GO -->|Forward Messages| WH
    WH -->|POST| EXT

Component Details

flowchart LR
    subgraph GoAPI["Go Bridge REST API"]
        direction TB
        SEND["/api/send"]
        DOWN["/api/download"]
        TYPE["/api/typing"]
        HEALTH["/api/health"]
    end

    subgraph MCPTools["MCP Tools (14 total)"]
        direction TB
        CONT["Contact Tools<br/>search_contacts, get_contact"]
        MSG["Message Tools<br/>list_messages, send_message, etc."]
        CHAT["Chat Tools<br/>list_chats, get_chat, etc."]
        MEDIA["Media Tools<br/>send_file, download_media, etc."]
    end

    MCPTools -->|HTTP Requests| GoAPI

Data Flow

sequenceDiagram
    participant User as User
    participant Claude as Claude Desktop
    participant MCP as Python MCP Server
    participant Bridge as Go Bridge
    participant WA as WhatsApp

    User->>Claude: "Send 'Hello' to Mom"
    Claude->>MCP: send_message(recipient, message)
    MCP->>Bridge: POST /api/send
    Bridge->>WA: Send via WebSocket
    WA-->>Bridge: Delivery confirmation
    Bridge-->>MCP: Success response
    MCP-->>Claude: Message sent
    Claude-->>User: "Message sent to Mom"

Incoming Message Flow

sequenceDiagram
    participant WA as WhatsApp
    participant Bridge as Go Bridge
    participant DB as SQLite
    participant WH as Webhook
    participant EXT as External Service

    WA->>Bridge: New message
    Bridge->>DB: Store message
    Bridge->>Bridge: Auto-download media
    Bridge->>WH: Forward to webhook
    WH->>EXT: POST with message data
    Note over EXT: Process incoming message

Development

AnyIO requires version 4.14.2 or later within major version 4. This replaces the older cap that excluded security and cancellation fixes. The offline suite includes a real MCP stdio initialization/list-tools/shutdown check with bridge startup disabled, so lifecycle regressions can be detected without an account.

Running Tests

pip install -e ".[dev]"
pytest -m "not integration"

Linting

# Python
ruff check .
ruff format .
mypy src

# Go
cd whatsapp-bridge
golangci-lint run

Building

# Go bridge
cd whatsapp-bridge
go build -o whatsapp-bridge

# Run the binary
./whatsapp-bridge

# During development (avoids stale binaries)
go run .

Releasing (Maintainers)

Releases use Release Please automation; maintainer steps and fallback procedures are documented in docs/RELEASING.md.

Troubleshooting

The optional launch.py --bridge-only launcher waits for the bridge process it starts; it does not immediately stop it on returning from startup. Normal MCP launches preserve the child server's exit status so supervisors can detect failures. Launcher health probes honor WHATSAPP_API_URL and the configured bridge host/port.

Authentication Issues

  • QR Code Not Displaying: Restart the bridge. Check terminal QR code support.

  • Device Limit Reached: Remove a linked device from WhatsApp Settings > Linked Devices.

  • No Messages Loading: Initial sync can take several minutes for large chat histories.

  • Out of Sync: Delete whatsapp-bridge/store/*.db files and re-authenticate.

Windows

Windows requires CGO for go-sqlite3. Install MSYS2 and enable CGO:

go env -w CGO_ENABLED=1
go run .

Security Notice

Caution: As with many MCP servers, this is subject to the lethal trifecta. Prompt injection could lead to private data exfiltration. Use with awareness.

License

MIT License - see LICENSE for details.

Credits & History

This project is a maintained fork of lharries/whatsapp-mcp, originally created by Luke Harries.

Why we forked: The original repository hasn't been updated since April 2025. We needed continued maintenance, bug fixes, and new features for production use.

Highlights since the fork:

  • /api/typing, /api/health, and webhook forwarding (with reply context + image media)

  • Auto-download of incoming media with collision-safe filenames

  • get_contact tool, sender_display field, and LID ↔ phone resolution via the whatsmeow store

  • Live capture of incoming voice/video calls into a calls table

  • --full-history-pair flag to request extended history at pair time

  • Resilience: recovers from StreamReplaced session conflicts; pinned anyio to dodge a cancel-scope regression

  • CI/CD with GitHub Actions, Release Please for automated versioning, and Dependabot

The full release-by-release list lives in CHANGELOG.md.

Recent contributors (huge thanks):

  • @edmenendez — call capture (#39), full-history flag (#37), caption surfacing (#42), media filename collisions (#40), download race fix (#41), LID matching (#43), contact resolution via whatsmeow store (#30)

  • @davidsimoes — StreamReplaced recovery (#27)

  • @davidggphy — LID → phone JID consistency (#12)

  • @maikol-solis — bridge run command fix (#23)

  • @DeetBot — anyio cancel-scope pin (#44)

And to Luke for creating the original project. See CONTRIBUTING.md if you'd like to join in.

Available Tools

13 tools
download_mediaA

Download media from a WhatsApp message and get the local file path.

Args: message_id: The ID of the message containing the media chat_jid: The JID of the chat containing the message

Returns: A dictionary containing success status, a status message, and the file path if successful

NameRequiredDescriptionDefault
chat_jidYes
message_idYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior3/5

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

With no annotations, the description carries the full behavioral burden. It discloses that the tool writes a local file and returns success status plus a file path, but it does not mention permissions, whether existing files are overwritten, or how failures are surfaced beyond a status flag.

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 first sentence front-loads the action and outcome, and the Args/Returns sections are compact. The formatting is slightly formulaic but no sentence is wasted.

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

Completeness4/5

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

The tool has two required parameters, no annotations, and an output schema. The description covers purpose, both parameters, and the return shape, which is sufficient for an agent to select and invoke it correctly. It lacks only minor operational details like file overwrite behavior or permissions.

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 0%, so the description must compensate. It documents both required parameters with their meaning: message_id identifies the message containing the media, and chat_jid identifies the containing chat. It does not specify JID or message-ID formats, but it covers all parameters.

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 (Download) and resource (media from a WhatsApp message) plus the direct outcome (local file path). This clearly distinguishes it from siblings like send_file, which moves data in the opposite direction.

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 by the action and the WhatsApp-message scope, but there is no explicit guidance on when to use this versus alternatives such as get_message_context or list_messages. No exclusions or prerequisites are stated.

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

get_chatC

Get WhatsApp chat metadata by JID.

Args: chat_jid: The JID of the chat to retrieve include_last_message: Whether to include the last message (default True)

NameRequiredDescriptionDefault
chat_jidYes
include_last_messageNo

Output Schema

NameRequiredDescription
resultYes

TDQS

C2.9/5.0
Behavior2/5

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

No annotations exist, so the description carries the full behavioral burden, yet it only says metadata is returned. It does not disclose what happens if the JID is unknown, whether the WhatsApp connection must be active, or how include_last_message changes the payload. The default value it mentions is already in 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?

The one-line purpose is front-loaded and the Args section is compact. It is efficiently sized, though the Args lines mostly restate the property names.

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 only two parameters and an output schema, the definition covers enough to invoke the tool, but it omits any error or precondition context and does not route the agent away from overlapping sibling tools.

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

Parameters3/5

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

Schema description coverage is 0%, so the Args block does add meaning: chat_jid identifies the target chat and include_last_message toggles inclusion of the most recent message. However, 'JID' is never explained in format terms (e.g. user@server) and what 'last message' includes is left ambiguous, so it only partially compensates for the schema gap.

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

Purpose4/5

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

States a specific verb and resource: 'Get WhatsApp chat metadata by JID.' An agent can tell this retrieves a single chat's metadata rather than listing chats or messages. It does not explicitly distinguish itself from near-siblings like get_direct_chat_by_contact or list_chats, which keeps it below 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 Guidelines2/5

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

There is no guidance on when to use this versus list_chats, get_direct_chat_by_contact, or get_contact_chats. The only contextual hint is that it needs a JID, which implies you must already know the chat identifier, but this is never stated as a precondition.

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

get_contactA

Look up a WhatsApp contact by phone number, LID, or full JID.

Automatically detects the identifier type and queries appropriately.

Args: identifier: Phone number, LID, or full JID. Examples: - "12025551234" (phone number) - "184125298348272" (LID - long numeric) - "12025551234@s.whatsapp.net" (phone JID) - "184125298348272@lid" (LID JID) phone_number: Backward-compatible alias for identifier. phone: Backward-compatible alias for identifier (matches README parameter name).

Returns: Dictionary with jid, name, display_name, is_lid, and resolved status

NameRequiredDescriptionDefault
phoneNo
identifierNo
phone_numberNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It does disclose useful behavior beyond the schema — automatic identifier-type detection and a 'resolved' status field — but never says what happens when no contact matches, whether it can create records, or whether any permissions are needed.

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 purpose and the auto-detection behavior are front-loaded in the first two sentences, and the Args block earns its space by supplying examples the schema lacks. The docstring-style formatting is slightly verbose but not wasteful.

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

Completeness3/5

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

An output schema exists, so the Returns section is redundant but harmless. The real gap is behavioral: for a lookup tool the not-found path matters, and the three overlapping optional parameters create resolution ambiguity that the description doesn't resolve.

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

Parameters4/5

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

Schema coverage is 0%, so the description must compensate, and it largely does: it gives concrete examples for phone number, LID, phone JID, and LID JID, and explains that phone_number and phone are backward-compatible aliases for identifier. It does not state that all three are optional/nullable or which one wins when more than one is supplied.

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

Purpose4/5

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

States a specific verb and resource ('look up a WhatsApp contact') and scopes it to exact identifiers (phone number, LID, full JID), which implicitly distinguishes it from the sibling search_contacts. It never names the sibling or states the distinction explicitly, 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?

Usage is implied by the identifier-based framing: use this when you already have an exact identifier. There is no explicit when-to-use / when-not guidance and no reference to search_contacts for fuzzy or name-based lookups, even though that sibling exists and is the obvious alternative.

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

get_contact_chatsB

Get all WhatsApp chats involving the contact.

Args: jid: The contact's JID to search for limit: Maximum number of chats to return (default 20) page: Page number for pagination (default 0)

NameRequiredDescriptionDefault
jidYes
pageNo
limitNo

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.3/5.0
Behavior3/5

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

No annotations exist, so the description carries the full burden; it implies a read-only retrieval and discloses the defaults for limit (20) and page (0). It does not state ordering, whether group chats count as "involving" the contact, or whether pagination past the last page errors or returns empty.

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?

One clear lead sentence followed by a compact args list; nothing is padded or redundant. The lead sentence is front-loaded, though it lacks the routing information that would make the brevity fully efficient.

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 output schema means return values needn't be described, and all three inputs are covered, so the basics are present. For a lookup tool with 0% schema coverage and no annotations, however, the ambiguous scope of "involving" leaves the agent unsure what a result set actually contains.

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 0%, but the args block documents all three parameters, including the required JID and the pagination defaults, compensating for the schema gap. It falls short of a 5 because it never explains the JID format or what happens when limit is exceeded.

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

Purpose4/5

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

The description states a specific verb and resource ("Get all WhatsApp chats involving the contact") and scopes results to a single contact's JID. This implicitly separates it from list_chats and get_chat, but it never names those siblings, so an agent must infer the distinction from the tool name alone.

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

Usage Guidelines2/5

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

There is no guidance on when to use this versus get_direct_chat_by_contact, list_chats, or get_last_interaction, all of which overlap in scope. The only hint is the word "involving," which is never explained, so an agent gets no explicit selection criteria.

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

get_direct_chat_by_contactB

Get WhatsApp chat metadata by sender phone number.

Args: sender_phone_number: The phone number to search for

NameRequiredDescriptionDefault
sender_phone_numberYes

Output Schema

NameRequiredDescription
resultYes

TDQS

B3/5.0
Behavior3/5

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

No annotations are provided, so the description carries the burden; the verb 'Get' does imply a read-only lookup and 'chat metadata' hints at the return shape. It does not say what happens when no chat exists for the number, whether the match is exact, or whether any auth scope is required.

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?

Short and front-loaded, with the key operation in the first clause. The 'Args:' block is boilerplate that adds nothing over the schema but is not harmful.

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

Completeness3/5

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

An output schema exists, so return values need not be explained, and a single-parameter read tool is inherently simple. Still, the one thing an agent could get wrong, the phone number format, is left unspecified.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate and it largely restates the field name ('The phone number to search for'). It never specifies the expected format (country code, E.164, digits only), which is the key ambiguity for a phone-number lookup.

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

Purpose4/5

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

States a specific verb and resource ('Get WhatsApp chat metadata') and scopes it by sender phone number, which distinguishes it from the broader list_chats and the id-based get_chat. It stops short of naming those siblings explicitly.

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

Usage Guidelines2/5

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

There is no guidance on when to use this versus list_chats, search_contacts, or get_chat, and no prerequisites or failure conditions are mentioned. The agent must infer from the name that this is the lookup-by-phone-number route.

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

get_last_interactionB

Get the most recent WhatsApp message involving the contact.

Args: jid: The JID of the contact to search for

Returns: Message dictionary with id, timestamp, sender, content, etc. or empty dict if not found.

NameRequiredDescriptionDefault
jidYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

B3.4/5.0
Behavior3/5

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

With no annotations provided, the description carries the full behavioral burden. It does disclose a useful edge case ('empty dict if not found'), implying a read-only lookup, but it says nothing about permissions, whether sent and received messages are both considered, or how media-only messages are handled.

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 purpose is front-loaded in the first sentence, followed by a conventional Args/Returns block. The structure is efficient, though slightly verbose for a one-parameter tool.

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

Completeness3/5

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

An output schema already exists, so the description's Returns block is largely redundant, and the remaining gaps are behavioral: nothing about ordering semantics, whether outgoing messages count, or authorization requirements. Adequate to invoke, but incomplete for a no-annotation 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 single parameter is at 0% schema description coverage, so the description must compensate. It states jid is 'the JID of the contact to search for,' which gives meaning but no format guidance (e.g., a phone-number-based JID or group JID) to help the agent construct a valid value.

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

Purpose4/5

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

The description opens with a specific verb and resource: 'Get the most recent WhatsApp message involving the contact.' This clearly delimits the result to a single, newest message, distinguishing it from list-style siblings like list_messages. It does not explicitly name an alternative, but the singleton scope makes the intent unambiguous.

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 this is a quick 'latest message' lookup rather than a search or history tool. There is no explicit guidance on when to prefer it over list_messages or get_message_context, and no prerequisites or exclusions are given.

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

get_message_contextA

Get context around a specific WhatsApp message.

Args: message_id: The ID of the message to get context for before: Number of messages to include before the target message (default 5) after: Number of messages to include after the target message (default 5) chat_jid: Chat containing the message; required when its ID occurs in multiple chats

NameRequiredDescriptionDefault
afterNo
beforeNo
chat_jidNo
message_idYes

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. 'Get' implies a read-only operation and the before/after defaults hint at the bounded window behavior, which is useful. It doesn't state what happens for an unknown message_id, ordering of returned messages, or any limits on before/after values.

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 front-loaded summary sentence followed by a compact Args list; every line adds information (including defaults and the conditional chat_jid rule) with no redundancy.

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-value explanation isn't needed, and all four parameters are documented with defaults and conditionality. The only gaps are edge-case behavior (unknown/missing message, window ordering) for a tool whose read-only nature is only implied.

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 0%, so the description must supply all parameter meaning — and it does, explaining message_id, the before/after counts with their default of 5, and the conditional requirement on chat_jid. It doesn't specify valid ranges for before/after, which would be the final increment.

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

Purpose4/5

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

States a specific verb and resource: 'Get context around a specific WhatsApp message', which is clearly a windowed read around one message. This is distinguishable from sibling list_messages by the 'around a specific message' framing, though the description doesn't name the sibling as an alternative.

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 by the resource ('context around a message'), and the chat_jid arg note gives a conditional usage hint ('required when its ID occurs in multiple chats'). However, there is no explicit when-to-use-this vs list_messages guidance and no stated preconditions for resolving a message_id.

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

list_chatsB

Get WhatsApp chats matching specified criteria.

Args: query: Search term to filter chats by name or JID limit: Max chats to return (default 50, max 200) page: Page number for pagination (default 0) include_last_message: Include the last message in each chat (default True) sort_by: "last_active" (default, most recent first) or "name" (alphabetical)

NameRequiredDescriptionDefault
pageNo
limitNo
queryNo
sort_byNolast_active
include_last_messageNo

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.3/5.0
Behavior3/5

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

No annotations exist, so the description carries the full behavioral burden. It adds useful operational facts — default limit 50 with a 200 cap, default page 0 pagination, and default sorting by last_active — but says nothing about read-only nature explicitly, permissions/auth requirements, or rate limits. Adequate but incomplete for a zero-annotation tool.

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

Conciseness4/5

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

Front-loaded with a one-line purpose followed by a compact, scannable per-parameter list. The 'Args:' scaffold is boilerplate but every line carries information, so there is minimal waste.

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

Completeness3/5

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

An output schema exists, so return values needn't be explained, and parameters are fully covered. What remains missing is sibling routing and any permission or safety context for a tool with no annotations — enough gaps to keep it at minimum-viable-plus rather than complete.

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

Parameters4/5

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

Schema description coverage is 0%, so the description must compensate, and it largely does: all five parameters are documented with defaults, the limit ceiling, and the two valid sort_by values (which the schema does not enumerate via enum). It is missing only the type/nullability nuance for query.

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

Purpose4/5

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

States a specific verb and resource (get WhatsApp chats) and hints at filtering criteria. However, it never distinguishes this from siblings like get_chat, get_contact_chats, or list_messages, so the agent must infer the boundary from the name alone.

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 when-to-use or when-not-to-use guidance and no mention of alternatives. With siblings such as get_contact_chats (chats for a specific contact) and get_chat (a single chat) present, the description should say which one to pick when scoping to one contact or one chat.

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

list_messagesA

Get WhatsApp messages matching specified criteria with optional context.

Each message includes sender_display showing "Name (phone)" for easy identification.

Args: after: ISO-8601 date string (e.g., "2026-01-01" or "2026-01-01T09:00:00") before: ISO-8601 date string (e.g., "2026-01-09" or "2026-01-09T18:00:00") sender_phone_number: Phone number to filter by sender (e.g., "12025551234") chat_jid: Chat JID to filter by (e.g., "12025551234@s.whatsapp.net" or group JID) query: Search term to filter messages by content limit: Max messages to return (default 50, max 500) page: Page number for pagination (default 0) include_context: Include surrounding messages for context (default True) context_before: Messages to include before each match (default 1) context_after: Messages to include after each match (default 1) sort_by: "newest" (default, most recent first) or "oldest" (chronological)

NameRequiredDescriptionDefault
pageNo
afterNo
limitNo
queryNo
beforeNo
sort_byNonewest
chat_jidNo
context_afterNo
context_beforeNo
include_contextNo
sender_phone_numberNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does well: it discloses defaults (limit 50, max 500, page 0, include_context True, 1 before/after), sort semantics, and the sender_display output shape. It omits that this is a read-only/non-destructive operation and says nothing about permissions or rate limits, which is the main remaining gap.

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

Conciseness4/5

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

A front-loaded one-line purpose followed by a compact Args block where every line adds concrete information; the sender_display note is placed early where it is useful. Only minor redundancy between include_context and the context_before/after defaults.

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?

Eleven optional parameters are all explained, defaults are stated, and an output schema exists so return values need not be enumerated. Missing only operational context (read-only nature, pagination totals) which would fully close the loop.

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 0%, so the description must compensate entirely, and it does: all 11 parameters get meaning, format, and examples (ISO-8601 dates, E.164-style phone, chat JID forms, sort_by enumerations) plus defaults and the max cap on limit. This is meaningfully richer than the bare schema types.

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

Purpose4/5

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

States a specific verb and resource ("Get WhatsApp messages") plus the notion of filtering by criteria and optionally pulling context. It is clear what the tool returns, but it never contrasts itself with the close sibling get_message_context, which also deals with surrounding context.

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

Usage Guidelines3/5

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

Usage is only implied: the parameter list suggests filtering by sender, chat, date, or query, and include_context/context_before/context_after imply context retrieval. There is no explicit when-to-use statement and no guidance to prefer get_message_context or list_chats under any condition.

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

search_contactsB

Search WhatsApp contacts by name or phone number.

Args: query: Search term to match against contact names or phone numbers

NameRequiredDescriptionDefault
queryYes

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.3/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden, and it discloses almost nothing behavioral: no statement on partial vs exact matching, case sensitivity, result limits, or ordering. That 'search' is non-destructive is inferable from the verb but not stated, and nothing warns about ambiguous matches.

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 sentence is front-loaded and unambiguous, and the Args block is short enough not to waste space. Slight redundancy in restating the parameter name, but every line adds a bit of meaning.

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

Completeness3/5

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

For a one-parameter read tool with an output schema, the basics are covered, so return values need no explanation. What is missing is search-specific behavior: whether multiple contacts can come back, how results are ordered, and what an empty result looks like.

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 0% (the property has only the title 'Query'), so the description must compensate, and it does by defining the term as matching against contact names or phone numbers. It still omits match semantics (substring, prefix, normalized phone format), which is the one thing an agent would most need.

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

Purpose4/5

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

States a specific verb (search) and resource (WhatsApp contacts) plus the matching keys (name or phone number), which distinguishes it from get_contact in the sibling list. It stops short of explicitly naming that sibling or noting that results may be multiple.

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

Usage Guidelines3/5

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

Usage is only implied: an agent can infer this is the lookup path when it lacks a contact ID, versus get_contact for direct retrieval. There is no explicit 'use this when / use X instead' routing, no mention of what happens when no match is found.

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

send_audio_messageA

Send any audio file as a WhatsApp audio message. For group messages use the JID.

If ffmpeg isn't installed, use send_file instead.

Args: recipient: The recipient — either a phone number with country code but no + or other symbols, or a JID (e.g., "123456789@s.whatsapp.net" or a group JID like "123456789@g.us") media_path: The absolute path to the audio file (will be converted to Opus .ogg if needed)

Returns: A dictionary containing success status and a status message

NameRequiredDescriptionDefault
recipientYes
media_pathYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations, the description carries the burden and does add meaningful behavioral context: automatic conversion to Opus .ogg if needed, the ffmpeg dependency, and the return shape. It does not disclose permission/auth requirements or the irreversibility of sending a WhatsApp message, which would be needed for a full 5.

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

Conciseness5/5

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

The purpose and the sibling fallback are front-loaded in the first two sentences, followed by compact Args/Returns sections. Every sentence adds information; there is no redundant restatement of the tool name.

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

Completeness4/5

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

For a two-parameter send tool with no annotations but an output schema, the description covers the critical call details: addressing formats, path expectations, auto-conversion, and the ffmpeg fallback. Missing authorization/side-effect notes keep it from being fully complete.

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

Parameters4/5

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

Schema description coverage is 0%, so the description must compensate. It documents both parameters well: recipient format (country code without symbols, or JID examples like '123456789@s.whatsapp.net' and '123456789@g.us') and media_path as an absolute path with conversion behavior. It could still specify supported input formats or relative-path behavior for a 5.

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

Purpose5/5

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

States a specific verb and resource ('Send any audio file as a WhatsApp audio message') and implicitly distinguishes itself from send_file by naming that sibling as the fallback when ffmpeg is missing. An agent can tell this is the audio-message sending tool, not generic file or text sending.

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 clear when-to-use guidance for the most relevant alternative: 'If ffmpeg isn't installed, use send_file instead.' It also clarifies group-message addressing via JID. It does not explicitly contrast with send_message for text, but the audio-vs-text distinction is implicit in the purpose.

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

send_fileA

Send a file (image / raw audio / video / document) via WhatsApp. For group messages use the JID.

Args: recipient: The recipient — either a phone number with country code but no + or other symbols, or a JID (e.g., "123456789@s.whatsapp.net" or a group JID like "123456789@g.us") media_path: The absolute path to the media file to send (image, video, document)

Returns: A dictionary containing success status and a status message

NameRequiredDescriptionDefault
recipientYes
media_pathYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

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

With no annotations, the description carries the full burden and does disclose supported media types, recipient formats, absolute-path requirement, and a return shape. Still, it omits important send-side behavior such as authentication needs, file size limits, rate limits, and failure handling.

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 front-loaded and organized with Args and Returns sections. The Returns section is somewhat redundant because an output schema exists, and the recipient explanation is a bit verbose, but there is little waste.

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 two-parameter send tool with an output schema, the description gives enough parameter detail to invoke it correctly. The main remaining gap is behavioral context around authentication, limits, and failure modes, which is not covered by annotations.

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 description coverage is 0%, so the description must compensate, and it does: recipient is explained as either a country-code phone number without symbols or a JID with examples, and media_path is described as an absolute path with supported file categories.

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 verb and resource: sending a file via WhatsApp, with supported media types listed. It does not explicitly distinguish this tool from the sibling send_audio_message, even though audio is mentioned, so it falls short of full sibling differentiation.

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 a concrete recipient rule for group messages: use the JID. However, it does not say when to use send_file rather than send_message or send_audio_message, nor does it state any exclusions or prerequisites.

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

send_messageA

Send a WhatsApp message to a person or group. For group chats use the JID.

Args: recipient: The recipient — either a phone number with country code but no + or other symbols, or a JID (e.g., "123456789@s.whatsapp.net" or a group JID like "123456789@g.us") message: The message text to send

Returns: A dictionary containing success status and a status message

NameRequiredDescriptionDefault
messageYes
recipientYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

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

With no annotations, the description carries the full burden. It discloses that sending is immediate and returns a success status, but says nothing about required auth, rate limits, whether the message is recallable, or what a failure looks like beyond a "status message"

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

Conciseness4/5

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

Front-loaded with the core action, then scoped parameter detail. The "Args:"/"Returns:" boilerplate is slightly redundant given a structured schema and output schema exist, but overall it is tight.

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

Completeness3/5

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

An output schema exists, so the Returns block is superfluous, and the critical gaps are behavioral: no mention of authentication requirements, delivery semantics, or error conditions for a side-effecting messaging tool with zero annotation coverage.

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

Parameters4/5

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

Schema coverage is 0%, so the description must compensate — and it does, spelling out the recipient format in detail (country code, no '+' or symbols, JID forms for direct and group chats). The message parameter is left as just "message text", which is self-evident but not enriched.

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 WhatsApp message") and narrows it to text messages by contrasting implicitly with siblings send_file and send_audio_message. The scope is unmistakable 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 Guidelines3/5

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

It provides a conditional routing hint for group chats ("use the JID"), but never states when to choose this tool over send_file or send_audio_message, nor any prerequisites such as needing an authenticated session or known contact.

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. 13 tool updatesv0.3.0
    • First observeddownload_media
    • First observedget_chat
    • First observedget_contact
    • First observedget_contact_chats
    • First observedget_direct_chat_by_contact
    • First observedget_last_interaction
    • First observedget_message_context
    • First observedlist_chats
    • First observedlist_messages
    • First observedsearch_contacts
    • First observedsend_audio_message
    • First observedsend_file
    • First observedsend_message

TDQS

A3.7/5.0

Scored across 13 tools

Disambiguation4/5

Most tools have clear, distinct purposes, but the chat-retrieval set has some overlap: list_chats, get_chat, get_direct_chat_by_contact, and get_contact_chats can be confusing depending on whether the agent has a contact, phone number, or JID. send_audio_message and send_file also overlap for audio files, though the description clarifies the distinction.

Naming Consistency5/5

All tools use consistent snake_case verb_noun naming (search_contacts, get_chat, list_messages, send_message, download_media, etc.). The pattern is predictable throughout despite a few longer names.

Tool Count5/5

At 13 tools, the set is well-scoped for a WhatsApp MCP server. Each tool maps to a meaningful contact, chat, message, send, or media operation without excessive surface area.

Completeness4/5

The surface covers the core WhatsApp workflows: contact lookup, chat listing, message reading/context, sending text/files/audio, and media download. Minor gaps remain around message editing/deletion, reactions, and group administration, but the main agent workflows are supported.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables Claude to read and send WhatsApp messages through a self-hosted REST API, supporting multi-user sessions, media, groups, contacts, and webhooks.
    2 npm
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables Claude to interact with WhatsApp: read chats, search messages, send messages with a mandatory confirmation step, and transcribe voice notes locally, all with encrypted storage and prompt-injection scrubbing.
    6
    MIT