Skip to main content
Glama

signal-mcp

Give your AI assistant a memory for Signal — privately, on your own machine.

Searchable message history · 80+ tools · groups, polls, mentions, labels · read-only mode · 100% local

Tests PyPI Python License: MIT Glama

signal-mcp is an MCP server and CLI built on signal-cli, the community-made, unofficial Signal client. It links to your existing Signal account as a device, keeps every message in a local database you can search, and lets an AI assistant like Claude read, search and — if you allow it — act on your chats. No cloud service, no third party: your messages stay on your computer.

You     What did the coach say about Sunday, and did anyone offer to bring the jerseys?

Claude  Daniel (coach): meet 10:15 at the hall, kickoff 11:00, ten boys confirmed.
        Elena and Mikko both replied — they'll bring the jerseys. Nothing needs
        an answer from you except confirming your son is coming.

You     Tell the group we'll be there, and tag the coach.

Claude  Sent to "U12 Team": "@Daniel we'll be there at 10:15 👍"

Illustrative example with made-up names.

Independent project — not affiliated with Signal. signal-mcp is not made, endorsed or supported by Signal Messenger or the Signal Foundation. It talks to Signal through signal-cli, an unofficial third-party client that you link to your account as an extra device (like Signal Desktop). Signal does not provide support for unofficial clients, and using one is at your own risk — see Signal's Terms of Service.

The same data from your terminal — this is real signal-mcp output on a demo database:

Why it exists

I built signal-mcp for a very ordinary reason: I'm a parent in my kids' football-team group chats and wanted my assistant to keep up with them — kickoff times, who's bringing the jerseys, which tag to set. I use it every day, against my own real Signal account, which is why safety (read-only mode, no file exfiltration, nothing leaving the machine) is built in rather than bolted on.

Related MCP server: mcp-signal

Why you want this

signal-cli is excellent at the Signal protocol and deliberately minimal everywhere else. signal-mcp adds the parts you need to actually use your messages:

  • A memory. signal-cli delivers a message and forgets it. signal-mcp stores everything — including messages you sent from your phone — in local SQLite, and can import your whole Signal Desktop history.

  • Search that works. Full-text search across all chats, filterable by sender and date range.

  • Real conversations. Paginated threads, unread counts, last-message previews — and names instead of +12025551234, even for group members who aren't in your contacts.

  • Everything Signal shows you. @mentions (resolved to names), polls, pins, link previews, quotes, voice notes, stickers, group member labels, join requests — nothing signal-cli reports is thrown away.

  • Full control when you want it. Send, reply, react, edit, delete, manage groups, schedule messages, set your profile — with a read-only switch for when you don't.

  • Zero babysitting. The daemon starts itself and restarts if it crashes; an optional background service captures messages while Claude isn't running; signal-mcp doctor tells you what's wrong if something is.

Quick start

brew install signal-cli                  # Linux: see Setup below
signal-cli link --name "MyMac"           # scan the QR code: Signal → Settings → Linked Devices
uv tool install signal-mcp
claude mcp add signal -- signal-mcp serve

Needs Python 3.12+, signal-cli 0.13+ and a Signal account on your phone. Restart Claude Code and ask "check my Signal messages". Works with any MCP client (Claude Code and Claude Desktop are what it is developed and tested with) — config snippets are in Setup.

What you can ask

Catch up

"What did I miss while I was offline?" · "Summarize the parents' group since Monday."

Find

"Find every message about the invoice." · "What did Anna say about the trip last week?"

Act

"Reply to Marco that Thursday works." · "Remind the team at 9:00 tomorrow." · "Create a poll for Friday's dinner."

Groups

"Who's waiting to join the group?" · "Set my label in the football group to my son's name."

Housekeeping

"Export my chat with Mom as CSV." · "Who hasn't messaged me in a month?" · "Delete that message for everyone."

Prefer the terminal? Everything is also a command — signal-mcp send, search, conversations, export, … (CLI usage). The CLI and MCP server share one store and one daemon.

Private and safe by design

  • 100% local. Messages live in SQLite on your disk; the daemon listens on localhost only. There is no signal-mcp cloud. (The only things that leave your machine are what you send through Signal itself and an optional webhook you configure.)

  • Read-only mode. SIGNAL_MCP_READONLY=1 hides and blocks every tool that sends, edits, deletes or changes settings — for assistants you don't fully trust with your account. See Step 7.

  • No file exfiltration. Anything that uploads a local file (attachments, avatars, link-preview images, sticker packs) only reads from an allow-list of folders (SIGNAL_MCP_SEND_ROOTS; default: your attachments folder, Downloads, Desktop, Documents) and never from hidden files or folders — so a message that says "send me ~/.ssh/id_ed25519" can't talk an assistant into it.

  • Irreversible means confirmed. Clearing the local store or terminating a group requires an explicit confirm.

  • Careful with secrets. The Signal Desktop import decrypts into a private (0700) folder, passes the key over stdin rather than the command line, and cleans up even when interrupted.

  • Honest caveat. Messages from other people are untrusted text that an AI will read. Read-only mode (or just not granting write access) is the strongest defence against a hostile message trying to steer your assistant.

What's new

1.40 closes the gap with signal-cli: incoming @mentions, polls, pins, previews and quotes are now captured; group member labels, bans, permissions and join requests; contact nicknames and notes; link previews, voice notes and stories on the sending side; and a fix that finally copies received attachments. See the changelog.

Setup

Step 1 — Install signal-cli

signal-mcp is a front-end for signal-cli, an independent, unofficial client that handles the Signal protocol.

macOS

brew install signal-cli

Linux Download the latest release from signal-cli releases, extract it, and put the signal-cli binary on your $PATH.

signal-cli needs to be linked to your existing Signal account (the same way you'd add a linked device in Signal mobile).

signal-cli link --name "MyMac"

This prints a QR code in your terminal. On your phone:

Signal → Settings → Linked Devices → + → scan the QR code

Once scanned, signal-cli is linked and ready.

Step 3 — Install signal-mcp

With uv (recommended):

uv tool install signal-mcp

With pip or pipx:

pip install signal-mcp
# or
pipx install signal-mcp

From source:

git clone https://github.com/googlarz/signal-mcp
cd signal-mcp
uv tool install .

Verify it works:

signal-mcp status
# → Account : +1234567890
# → Daemon  : stopped (port 7583)

Step 4 — Connect to Claude Code

claude mcp add signal -- signal-mcp serve

Restart Claude Code. Signal tools appear automatically — ask Claude "check my Signal messages" to confirm.

Claude Code — global (~/.claude.json):

{
  "mcpServers": {
    "signal": {
      "command": "uvx",
      "args": ["signal-mcp", "serve"]
    }
  }
}

Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "signal": {
      "command": "uvx",
      "args": ["signal-mcp", "serve"]
    }
  }
}

Claude Desktop uses a restricted PATH — uvx resolves the tool without needing signal-mcp on your shell's PATH.

Per-project (.mcp.json):

{
  "mcpServers": {
    "signal": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/signal-mcp", "signal-mcp", "serve"]
    }
  }
}

Step 5 — (Optional) Import Signal Desktop history

If you use Signal Desktop, import your full message history in one command.

macOS

brew install sqlcipher       # required for decryption
signal-mcp import-desktop    # macOS will prompt for Keychain access — click Allow

Linux (Debian/Ubuntu shown — use your distribution's packages elsewhere)

sudo apt install sqlcipher libsecret-tools   # decryption + keyring lookup (secret-tool)
signal-mcp import-desktop                    # your keyring must be unlocked

Step 6 — (Optional) Enable background message capture

signal-cli only delivers messages when polled. Install the background service so nothing is missed:

signal-mcp install-service   # starts on login, works on macOS and Linux

Step 7 — (Optional) Read-only mode

Set SIGNAL_MCP_READONLY=1 in the environment to restrict the server to read-only tools (listing, searching, and exporting existing local/remote state). Tools that send, edit, delete, or otherwise mutate your Signal account — messages, contacts, groups, devices, and settings — are hidden from tool listings and rejected if called directly. Useful when connecting an AI client you don't fully trust with write access to your real Signal account.

Troubleshooting

Start with signal-mcp doctor — it checks signal-cli, your linked account, the daemon, and message capture, and says which one is broken.

Symptom

Cause and fix

doctor reports Devices readable — ReadTimeout, or list_devices hangs

A bug in signal-cli 0.14.8 (listDevices crashes inside libsignal). Fixed upstream, not yet released; everything else works. Upgrade signal-cli once 0.14.9 ships.

"Unknown sender" / bare numbers in a group

Names come from your contacts, then Signal profiles (also for non-contacts), then Signal Desktop. Someone with none of these stays a number — import-desktop brings in Desktop's names.

import-desktop fails on Linux

Needs sqlcipher and libsecret-tools, and an unlocked GNOME Keyring. KWallet-only setups aren't supported.

Messages missing while Claude wasn't running

Install the background service: signal-mcp install-service.

Attachment has no local file

Received files are copied to ~/Downloads/signal-attachments/. If one is missing, get_attachment retrieves it from signal-cli's own attachment store by id.

MCP Tools

Messaging

Tool

Description

send_message

Send a text message to a contact (by number, or by Signal username). Supports quoted replies (quoted text is filled in from your local store), link previews, no_urgent, notify_self, end_session, story replies, and — with formatting: true — Signal formatting from **bold**, *italic*, ~~strike~~, `mono` and ||spoiler||.

send_group_message

Send a text message to a group. Supports quoted replies, @mentions, link previews, and — with formatting: true — real Signal formatting from **bold**, *italic*, ~~strike~~, `mono` and ||spoiler|| (mention offsets are adjusted for you).

send_attachment

Send a file or image to a contact. Supports captions, view-once and voice_note.

send_group_attachment

Send a file or image to a group. Supports captions, view-once and voice_note.

send_note_to_self

Save a note to yourself (Signal's saved messages).

receive_messages

Poll for new incoming messages and delivery receipts. Optional max_messages.

receive_direct

Receive by calling signal-cli directly (no daemon) — for when the background service isn't running. Optional max_messages and ignore_* filters.

get_unread

Get messages not yet marked as read from local store.

edit_message

Edit a previously sent message (DM or group). Updates local store. Incoming edits from contacts also update the stored copy in-place.

delete_message

Remote-delete (unsend) a sent DM.

delete_group_message

Remote-delete a sent group message.

react_to_message

React to a message with an emoji (DM or group). Set remove=true to unreact.

pin_message

Pin a message in a DM or group conversation.

unpin_message

Unpin a message in a DM or group conversation.

admin_delete_message

Group admin: delete any message in a group you administer.

set_typing

Send (or stop) a typing indicator in a chat or group.

send_story

Post an image or video to your Signal story, optionally to a group story.

send_read_receipt

Mark messages as read. Also updates local store.

send_sticker

Send a sticker to a contact.

send_group_sticker

Send a sticker to a group.

Configuration

Tool

Description

update_configuration

Toggle read receipts, typing indicators, link previews, or sealed sender indicators.

Sticker Packs

Tool

Description

list_sticker_packs

List all installed sticker packs with pack_id and sticker IDs for send_sticker.

add_sticker_pack

Install a sticker pack from a signal.art URL. Returns the pack ID for use with get_sticker/send_sticker.

get_sticker

Retrieve a single sticker image as base64.

upload_sticker_pack

Upload and publish a sticker pack from a local manifest.json or zip. Returns the signal.art URL.

Contacts

Tool

Description

list_contacts

All contacts with names and numbers. Supports optional search filter.

get_profile

Get profile info for a contact.

update_contact

Set a local display name for a contact.

block_contact

Block a contact.

unblock_contact

Unblock a contact.

remove_contact

Remove a contact from the local list.

update_profile

Update your own name, about text, or avatar.

get_own_number

Get the Signal number this server is running as.

Message output now carries everything signal-cli reports for incoming messages, when present: mentions (with body_resolved, the text with @name in place of the placeholder), text_styles, previews, quote (author and text), voice_note, sticker, polls (poll_create / poll_vote / poll_terminate), pins, story replies and shared contacts. Remote and admin deletes flag the stored message (remote_deleted, admin_deleted_by) instead of erasing your local copy.

Groups

Tool

Description

list_groups

All groups with members and metadata: member labels (label, label_emoji), pending/requesting/banned members, permissions, invite link. Optional group_id filter.

create_group

Create a new Signal group.

join_group

Join a group via invite link.

update_group

Rename, add/remove members, promote/demote admins, set expiry timer, avatar, ban/unban, reset invite link, group permissions, and your own member label (member_label, member_label_emoji — only your own label can be set).

leave_group

Leave a group. A sole admin must name a successor (admins); delete also removes the local group data.

terminate_group

Permanently end a group for every member. Irreversible; requires confirm: true.

Tool

Description

list_conversations

All conversations ordered by most recent message.

get_conversation

Message history with a contact or group. Supports since, limit, and offset for pagination.

search_messages

Full-text search (FTS5) across all stored messages. Supports sender, since/until (ISO date range; until exclusive), limit, and offset.

store_stats

Total message count, oldest and newest message dates.

mark_as_unread

Mark one or more stored messages as unread.

get_user_status

Check whether phone numbers are registered Signal users.

send_sync_request

Request sync of messages/contacts/groups from your primary device.

send_contacts_sync

Push your contacts list to all linked devices.

send_message_request_response

Accept or decline a message request from an unknown sender.

Security & Devices

Tool

Description

list_identities

List identity keys and trust levels (safety numbers).

trust_identity

Trust a contact's identity key after verifying their safety number.

list_devices

List all devices linked to your account.

add_device

Link a new device using a device link URI.

remove_device

Unlink a device by ID.

update_device

Rename a linked device.

list_accounts

List all Signal accounts configured in signal-cli on this machine.

update_account

Update account settings: device name, discoverability, number sharing, username.

set_pin

Set the Signal registration lock PIN.

remove_pin

Remove the Signal registration lock PIN.

get_avatar

Retrieve the avatar image for a contact or group as base64.

Polls

Tool

Description

create_poll

Create a poll in a group conversation.

vote_poll

Cast a vote on an existing poll.

terminate_poll

End a poll and prevent further votes.

Disappearing Messages

Tool

Description

set_expiration_timer

Set or disable disappearing messages for any DM or group.

Scheduling

Tool

Description

schedule_message

Queue a message for later (send_at, ISO datetime) to a contact or group.

list_scheduled_messages

List queued messages (include_done adds sent, cancelled and failed ones).

cancel_scheduled_message

Cancel a pending scheduled message by id.

run_scheduled_messages

Send everything that is due now. Nothing sends scheduled messages by itself — call this tool, or run signal-mcp run-scheduled (e.g. from cron).

Webhooks

Tool

Description

set_webhook

Set (or clear) a URL that receives a JSON POST for each incoming message.

get_webhook

Show the configured webhook URL.

Data & Import

Tool

Description

import_desktop

One-time full import of all historical messages from Signal Desktop. Requires sqlcipher.

sync_desktop

Incremental sync from Signal Desktop — imports only messages newer than the last sync. Fast on repeat calls. First call behaves like import_desktop.

list_attachments

List all locally downloaded attachments (photos, files received via Signal).

get_attachment

Get details about a downloaded attachment by filename; if it is not in the local attachments folder it is fetched from signal-cli by attachment id.

clear_local_store

Delete ALL locally stored messages (requires confirm: true). Does not unsend from Signal.

delete_local_messages

Delete locally stored messages for one contact or group.

export_messages

Export stored messages as JSON or CSV. Supports recipient and since filters.

CLI Usage

# Status & daemon
signal-mcp status                          # account + daemon info
signal-mcp doctor                          # onboarding smoke test: signal-cli, account, daemon, receive health
signal-mcp daemon                          # start daemon in foreground
signal-mcp stop                            # stop the daemon

# Send & receive
signal-mcp send +1234567890 "Hello!"
signal-mcp send +1234567890 "**Heads up** — *lunch at 1*" --format
signal-mcp send-group <group_id> "Hey!"
signal-mcp send-group <group_id> "**Kickoff** is at *11:00*" --format   # bold + italic
signal-mcp note "Remember to buy milk"     # save a note to yourself
signal-mcp receive                         # poll once
signal-mcp receive --watch                 # keep watching (saves to store)

# Edit
signal-mcp edit +1234567890 <timestamp> "corrected text"
signal-mcp edit <group_id> <timestamp> "corrected text"

# React / delete / block
signal-mcp react +1234567890 <timestamp> +1234567890 👍
signal-mcp delete +1234567890 <timestamp>  # unsend a message you sent
signal-mcp block +1234567890               # and: signal-mcp unblock ...

# Pin / unpin / admin-delete messages
signal-mcp pin +1234567890 <timestamp> +1234567890
signal-mcp unpin +1234567890 <timestamp> +1234567890
signal-mcp admin-delete <group_id> <timestamp> +1234567890

# Devices
signal-mcp update-device <device_id> "My Laptop"

# Contacts & groups
signal-mcp contacts
signal-mcp contacts --json
signal-mcp find-contact anna               # add --all-recipients to include non-contacts (e.g. group members)
signal-mcp groups
signal-mcp group-label <group_id> "Anna"   # set YOUR OWN member label in a group
signal-mcp conversations                   # list all chats with unread count + last message

# History & search
signal-mcp history +1234567890
signal-mcp history +1234567890 --limit 20
signal-mcp history +1234567890 --limit 20 --offset 20   # page 2
signal-mcp history +1234567890 --since 2024-01-01
signal-mcp search "keyword"
signal-mcp search "keyword" --sender +1234567890   # restrict to one contact
signal-mcp search "keyword" --limit 20
signal-mcp search "invoice" --since 2024-01-01 --until 2024-02-01
signal-mcp store-stats

# Export
signal-mcp export                                          # all messages as JSON to stdout
signal-mcp export messages.json                            # save to file
signal-mcp export messages.csv --format csv                # CSV format
signal-mcp export --recipient +1234567890 --format csv     # one conversation
signal-mcp export --since 2024-01-01                       # messages from date

# Scheduled messages
signal-mcp schedule-send +1234567890 "Happy birthday!" --at "2027-01-01 09:00"
signal-mcp scheduled                       # list; cancel with: signal-mcp cancel-scheduled <id>
signal-mcp run-scheduled                   # send whatever is due now

# Stories & webhooks
signal-mcp story photo.jpg
signal-mcp set-webhook http://localhost:8080/signal   # run without a URL to clear
signal-mcp get-webhook

# Housekeeping
signal-mcp prune --days 180                # delete local messages older than 180 days

# Signal Desktop import — one-time full import
signal-mcp import-desktop
signal-mcp sync-desktop                    # incremental: only new messages since last sync

# Background service (macOS LaunchAgent or Linux systemd)
signal-mcp install-service    # auto-starts on login, captures all messages
signal-mcp uninstall-service

# MCP server (for Claude Code)
signal-mcp serve

Getting full message history

signal-cli only delivers new messages — it has no history API. Two ways to get history:

Going forward (captures everything from now on):

signal-mcp install-service   # background watcher, auto-starts on login

Retroactively (imports everything from Signal Desktop):

signal-mcp import-desktop    # macOS prompts for Keychain access; Linux needs an unlocked keyring

Run both for complete coverage.

Architecture

                    ┌─────────────────────────────────┐
                    │  signal-cli daemon  (:7583)      │
                    │  Signal protocol / libsignal     │
                    └──────────┬──────────────┬────────┘
                               │ sends/receives│
                    ┌──────────▼──────────┐   │ (when no service)
                    │  background service  │   │
                    │  LaunchAgent/systemd │   │
                    └──────────┬──────────┘   │
                               │ writes        │
                    ┌──────────▼──────────────▼────────┐
                    │  SQLite store                     │
                    │  ~/.local/share/signal-mcp/       │
                    │  messages.db  (FTS5 indexed)      │
                    └────────────────┬─────────────────┘
                                     │ reads/writes
                   ┌─────────────────┼─────────────────┐
                   │                 │                  │
        ┌──────────▼──────┐ ┌────────▼───────┐ ┌──────▼──────────┐
        │  Claude Code /  │ │  signal-mcp    │ │  signal-mcp CLI │
        │  Claude Desktop │ │  serve (MCP)   │ │  (terminal)     │
        │  (asks Claude)  │ └────────────────┘ └─────────────────┘
        └─────────────────┘

How it works:

get_unread is the primary "check for new messages" tool. If the background service is installed, it reads straight from the store (the service keeps it up to date). Otherwise it polls signal-cli first (debounced to once every 30 seconds) and includes a _warning suggesting signal-mcp install-service. list_conversations is a pure store read — fast, no polling.

The daemon starts automatically on first use. Attachments are saved to ~/Downloads/signal-attachments/.

signal-cli Coverage

signal-mcp wraps the signal-cli JSON-RPC daemon. Here's what is and isn't covered:

Covered (81 tools)

signal-cli command

signal-mcp tool

send

send_message, send_group_message, send_note_to_self, send_attachment, send_group_attachment, send_sticker, send_group_sticker

receive

receive_messages (streaming), get_unread

listContacts

list_contacts, find_contact (all_recipients also returns non-contacts, e.g. other group members)

listGroups

list_groups

listDevices

list_devices

listIdentities

list_identities

listStickerPacks

list_sticker_packs

getUserStatus

get_user_status

getAttachment

get_attachment, list_attachments

getAvatar

get_avatar

block / unblock

block_contact / unblock_contact

removeContact

remove_contact

updateContact

update_contact

trust

trust_identity

joinGroup

join_group

quitGroup

leave_group

updateGroup

update_group, create_group

addDevice / removeDevice / updateDevice

add_device / remove_device / update_device

sendReaction

react_to_message

sendTyping

set_typing

sendReceipt

send_read_receipt

sendSyncRequest

send_sync_request

sendContacts

send_contacts_sync

sendAdminDelete

admin_delete_message

sendPinMessage / sendUnpinMessage

pin_message / unpin_message

sendPollCreate / sendPollVote / sendPollTerminate

create_poll / vote_poll / terminate_poll

sendStory

send_story

terminateGroup

terminate_group

sendMessageRequestResponse

send_message_request_response

remoteDelete

delete_message, delete_group_message

editMessage

edit_message

updateProfile

update_profile

updateConfiguration

update_configuration

addStickerPack

add_sticker_pack

getSticker

get_sticker

uploadStickerPack

upload_sticker_pack

listAccounts

list_accounts

updateAccount

update_account

setPin / removePin

set_pin / remove_pin

startChangeNumber / finishChangeNumber

start_change_number / finish_change_number

submitRateLimitChallenge

submit_rate_limit_challenge

Plus tools with no direct signal-cli equivalent: get_conversation, search_messages, list_conversations, store_stats, import_desktop, sync_desktop, export_messages, mark_as_unread, clear_local_store, delete_local_messages, prune_store.

Not covered

These commands are deliberately excluded — either not feasible to implement as MCP tools, or consciously left out (see the reason for each):

signal-cli command

Why

acceptCall / hangupCall / rejectCall / startCall / listCalls

Voice/video calls require WebRTC and an active media stack — not feasible via MCP

register / verify / link / unregister

One-time account setup; must be done before installing signal-mcp

deleteLocalAccountData

Irreversibly destroys all local Signal data; too destructive to expose

sendPaymentNotification

Only forwards a MobileCoin receipt produced by an external wallet; signal-mcp cannot create or verify one

Development

git clone https://github.com/googlarz/signal-mcp
cd signal-mcp
uv sync --dev
uv run pytest
uv run pytest --cov --cov-report=term-missing

573 tests, 100% line coverage across all modules. All tests are fully mocked — no signal-cli installation or Signal account required to run them.

See CONTRIBUTING.md for how to add new tools.

License

MIT — see LICENSE.

Available Tools

81 tools
add_deviceA

Link a new device (e.g. Signal Desktop or another signal-cli) to your account. uri (required): the device-link URI (sgnl://linkdevice?...) shown by the new device as a QR code or printed by 'signal-cli link'. Only works when signal-mcp is the account's primary device — fails with 'This command doesn't work on linked devices' if signal-mcp was set up via signal-cli link. Also fails on a malformed or expired link or when the account already has the maximum number of linked devices. The linked device gets full access to the account; never use a URI from an untrusted source. Returns status 'device linked'; confirm with list_devices, undo with remove_device.

ParametersJSON Schema
NameRequiredDescriptionDefault
uriYesDevice link URI (sgnl://linkdevice?...) from the new device's QR code or signal-cli link output

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only declare the generic safety profile (readOnly=false, destructive=false, openWorld=true, idempotent=false). The description adds what annotations cannot: the exact error string returned when run on a linked device, the three failure modes, the fact that the linked device gains full account access, and an explicit security warning never to use an untrusted URI.

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 action, then prerequisites, failure modes, and cleanup path in a tight sequence; every sentence carries operational information. It is on the denser side for a one-parameter tool, but no sentence is filler.

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

Completeness5/5

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

For a single-parameter, no-output-schema mutation tool, it covers everything an agent needs: prerequisite state, error conditions, security caveat, the return status string ('device linked'), and the follow-up/undo 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 coverage is 100% and the single uri parameter is fully described in the schema, so the description's mention of 'the device-link URI (sgnl://linkdevice?...) shown as a QR code or printed by signal-cli link' mostly reinforces existing schema text. Baseline 3 applies when the schema carries the semantics.

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 — 'Link a new device ... to your account' — with an example of what a device is. It is immediately distinguishable from siblings like list_devices, update_device, and remove_device.

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

Usage Guidelines5/5

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

Explicitly states the precondition (only works when signal-mcp is the primary device), the failure conditions (linked-device setup, malformed/expired link, device limit), and routes the agent to alternatives: confirm with list_devices, undo with remove_device.

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

add_sticker_packA
Idempotent

Install an existing sticker pack on this Signal account from its signal.art link. uri (required): https://signal.art/addstickers/#pack_id=&pack_key=; both pack_id and pack_key are needed. Installing the same pack again has no further effect. Returns {status: 'installed', pack_id} with pack_id parsed from the uri, ready for send_sticker, send_group_sticker or get_sticker; call list_sticker_packs to see the sticker ids and emoji in it. Use upload_sticker_pack instead to publish a new pack of your own images.

ParametersJSON Schema
NameRequiredDescriptionDefault
uriYesSticker pack URL (https://signal.art/addstickers/#pack_id=...&pack_key=...)

TDQS

A4.6/5.0
Behavior4/5

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

Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=true, openWorldHint=true), but the description adds concrete meaning: the exact return shape {status: 'installed', pack_id}, that pack_id is parsed from the uri, and that re-installation is a no-op. It stops short of mentioning any auth or rate-limit considerations, but the added behavioral context is real.

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 the input constraint, then the return value and routing. Every sentence carries information, though the inline uri format with angle-bracket placeholders makes the middle clause slightly dense.

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

Completeness5/5

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

With no output schema, the description compensates by documenting the return payload and the parsed pack_id, and it names the downstream tools (send_sticker, send_group_sticker, get_sticker) plus the inspection tool (list_sticker_packs). Nothing needed to invoke this correctly is missing.

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

Parameters4/5

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

Schema coverage is 100% with a single uri parameter, but the description goes beyond the schema by spelling out the required fragment structure (pack_id=<hex>&pack_key=<hex>) and stressing that both pack_id and pack_key must be present — a validation detail the schema's terse description does not convey.

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 ('Install') plus resource ('an existing sticker pack on this Signal account') and the required input format (signal.art link). It also explicitly distinguishes itself from upload_sticker_pack, which publishes new packs, so an agent can disambiguate without reading either schema.

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

Usage Guidelines5/5

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

Gives the when (install an existing pack via signal.art uri), the when-not/alternative (use upload_sticker_pack to publish your own images), and the repeat-call behavior (installing the same pack again has no further effect). It also routes to list_sticker_packs for inspecting pack contents.

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

admin_delete_messageA
DestructiveIdempotent

As a group admin, delete any member's message in that group for all participants. For your own messages use delete_group_message (group) or delete_message (DM); for local-only removal delete_local_messages. Requires admin rights — check is_admin in list_groups. group_id: from list_groups; target_author: E.164 number of the message's sender; target_timestamp: its ms timestamp (message id in get_conversation). Irreversible; contacts Signal's servers; the local store copy is kept. Returns {status: 'message deleted by admin'}.

ParametersJSON Schema
NameRequiredDescriptionDefault
group_idYesGroup ID where the message was sent (get from list_groups)
target_authorYesPhone number of the user who sent the message
target_timestampYesTimestamp of the message to delete (from get_conversation)

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already declare destructiveHint=true and openWorldHint=true, but the description adds context annotations cannot express: 'Irreversible; contacts Signal's servers; the local store copy is kept.' That local-store nuance is non-obvious and material to the caller's decision.

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?

Purpose is front-loaded, followed by alternatives, prerequisites, and parameter sourcing in tight clauses. Every sentence carries operational value with no filler.

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

Completeness5/5

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

Even without an output schema, the description documents the return shape (returns {status: 'message deleted by admin'}), the permissions requirement, the server/local split, and sibling routing. Nothing an agent needs to invoke it correctly is missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds format detail beyond the schema — E.164 numbering for target_author and that target_timestamp is the message id 'in ms' from get_conversation. These sharpen how to supply the values.

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 ('delete'), resource ('any member's message'), and scope ('in that group for all participants'), and explicitly distinguishes itself from delete_group_message, delete_message, and delete_local_messages. An agent can identify this tool without opening any sibling schema.

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

Usage Guidelines5/5

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

Names each alternative and the condition that selects it (own messages vs. member messages, group vs. DM, server vs. local removal), and states the prerequisite plus how to verify it ('check is_admin in list_groups'). This is explicit when-to-use/when-not guidance.

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

block_contactA
Idempotent

Block a contact so you stop receiving their messages and calls. number (required, E.164). Only works when signal-mcp is the account's primary device — fails with 'This command doesn't work on linked devices' if signal-mcp was set up via signal-cli link. The contact is not notified. The blocked list is synced to your linked devices, and if you share no group with them your profile key is rotated so they lose access to your profile updates. Message history is kept. Blocking an already blocked contact is a no-op. Reversible with unblock_contact. To only delete the local contact entry without blocking, use remove_contact. Returns status 'blocked' and number.

ParametersJSON Schema
NameRequiredDescriptionDefault
numberYesPhone number to block (E.164 format, e.g. +1234567890)

TDQS

A4.7/5.0
Behavior5/5

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

Annotations only say destructiveHint=false and idempotentHint=true; the description adds substantial context beyond them: the primary-device precondition and error string, that the contact is not notified, that the blocked list syncs to linked devices, that the profile key is rotated when no shared group exists, that message history is kept, and that re-blocking is a no-op (consistent with idempotentHint).

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?

Front-loaded with purpose, then constraints, side effects and the alternative tool. Despite being a dense paragraph, every sentence carries distinct, decision-relevant information and none is filler.

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

Completeness5/5

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

With no output schema, the description compensates by stating the return value ('status \'blocked\' and number'). Combined with preconditions, side effects, reversibility and the no-op case, an agent has everything needed to call this correctly.

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

Parameters3/5

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

Schema description coverage is 100% and the single parameter already documents E.164 format with an example. The description restates 'number (required, E.164)' but adds no new syntax or constraint beyond the schema, so the baseline 3 applies.

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

Purpose5/5

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

The description leads with a specific verb and resource plus the user-visible effect: 'Block a contact so you stop receiving their messages and calls.' It clearly distinguishes itself from sibling tools it is often confused with (remove_contact deletes the local entry only; unblock_contact reverses this).

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

Usage Guidelines5/5

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

Explicit when-it-works precondition ('Only works when signal-mcp is the account's primary device'), the exact failure message on linked devices, and a named alternative ('To only delete the local contact entry without blocking, use remove_contact'). Reversibility with unblock_contact is also stated.

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

cancel_scheduled_messageA
DestructiveIdempotent

Cancel one pending scheduled message so it will never be sent. job_id (required, integer): the id from schedule_message or list_scheduled_messages. Local only; the job stays in the list with status 'cancelled' and cannot be re-activated (schedule it again instead). Returns {status: 'cancelled', job_id}, or an error if no pending job has that id (already sent, failed, cancelled or unknown).

ParametersJSON Schema
NameRequiredDescriptionDefault
job_idYesScheduled message job ID from list_scheduled_messages

TDQS

A4.7/5.0
Behavior5/5

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

Goes well beyond the annotations by disclosing that the operation is local-only, that the job remains in the list with status 'cancelled', that it is irreversible without rescheduling, and that an error is returned when no pending job matches (already sent, failed, cancelled, or unknown). That is exactly the mutation/irreversibility context an agent needs.

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

Conciseness5/5

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

One dense paragraph that front-loads the action and outcome, then layers id provenance, behavioral caveats, and return shape. No sentence is filler.

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

Completeness5/5

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

With annotations covering the safety profile (destructive, idempotent, non-read-only) and no output schema, the description supplies the missing return shape and failure modes. Nothing an agent needs to invoke this correctly is absent.

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

Parameters4/5

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

Schema coverage is already 100%, so the baseline is 3, but the description adds value by naming both source tools for the id and tying id validity to the error case. It still does not clarify whether the id is globally unique or per-account, so it stops short of 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 ('Cancel one pending scheduled message') plus the outcome ('so it will never be sent'), which cleanly separates it from siblings like delete_message, schedule_message, and run_scheduled_messages.

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

Usage Guidelines4/5

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

Names the tools that produce the required id (schedule_message, list_scheduled_messages) and routes the agent away from re-activation ('cannot be re-activated; schedule it again instead'). It gives clear context but never states when this should be preferred over other message-removal tools such as delete_message.

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

clear_local_storeA
DestructiveIdempotent

Delete ALL messages and attachment records from signal-mcp's local database. confirm (boolean, required) must be exactly true, otherwise nothing is deleted and an error is returned. Local only: nothing is deleted from Signal, your phone or other devices, and downloaded attachment files on disk are left in place. Irreversible except by re-importing (import_desktop) or receiving again. Returns {deleted: count, status: 'cleared'}. Use delete_local_messages to clear one conversation, prune_store to drop only old messages; delete_message unsends a message in Signal.

ParametersJSON Schema
NameRequiredDescriptionDefault
confirmYesMust be true to proceed — prevents accidental deletion

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, but the description goes well beyond them: the confirm guard and its failure mode, the local-only blast radius (nothing removed from Signal, phone, or other devices), the fact that downloaded attachment files on disk survive, and irreversibility except via re-import. That is the extra behavioral context annotations cannot carry.

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

Conciseness5/5

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

Four dense sentences, all front-loaded: what it destroys, the guard, the blast radius, the recovery path, the return shape. No filler and no repetition of the name.

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

Completeness5/5

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

For a one-parameter irreversible mutation with no output schema, the description supplies everything needed: destruction scope, safety gate, side-effect boundaries, reversibility, and even the return shape ({deleted: count, status: 'cleared'}). Nothing an agent needs before calling it is missing.

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

Parameters4/5

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

Schema coverage is 100% and the single parameter is self-documenting, so the baseline is 3. The description adds genuine meaning beyond the schema's 'Must be true to proceed' by specifying the semantics are exact — confirm must be exactly true, otherwise nothing is deleted and an error is returned.

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 (delete), resource (ALL messages and attachment records), and scope (signal-mcp's local database), with 'ALL' and 'local' doing real disambiguating work against siblings that also delete things. An agent can distinguish it from delete_local_messages, prune_store, and delete_message without opening any schema.

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

Usage Guidelines5/5

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

Explicitly routes the agent: delete_local_messages for a single conversation, prune_store for old messages only, delete_message for unsending in Signal. It also names the recovery path (import_desktop, re-receive). This is exactly the when/when-not/alternatives guidance the dimension asks for.

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

create_groupA

Create a new Signal group with you as admin. name (required) is the group name shown to everyone; members (required) is a list of E.164 phone numbers to add; description (optional) is the group info text; avatar (optional) is a local image path, which must be inside the allowed send folders (SIGNAL_MCP_SEND_ROOTS). Contacts Signal's servers and notifies every member; not idempotent — calling twice creates two groups. Returns status, groupId (base64; use it as group_id elsewhere), timestamp and per-member send results. Use update_group to change an existing group and send_group_message to post in it.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesGroup name visible to all members
avatarNoOptional local image file path for the group avatar
membersYesPhone numbers (E.164) of initial members to invite
descriptionNoOptional group description shown in group info

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false, idempotentHint=false and openWorldHint=true, but the description adds the concrete consequences: it contacts Signal's servers, notifies every member, creates a second group if called twice, and discloses the returned fields. It does not cover permission/admin-setup requirements or rate limits, so it stops short of a 5.

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

Conciseness4/5

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

Front-loaded with the core action, then parameters, side effects, returns and alternatives in a compact sequence. It is dense with clauses but each sentence carries distinct information; no filler.

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

Completeness5/5

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

With no output schema, the description compensates by enumerating return fields (status, groupId, timestamp, per-member results). Combined with side effects, path constraints and sibling routing, an agent has everything needed to call it correctly.

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 100%, so the baseline is 3, but the description earns more: it specifies members must be E.164 and that avatar must reside inside SIGNAL_MCP_SEND_ROOTS, a path constraint the schema does not state. It also clarifies how the returned groupId is reused as group_id.

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

Purpose5/5

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

States a specific verb and resource ('Create a new Signal group') plus the implicit role ('with you as admin'). It names two sibling tools it is not (update_group, send_group_message), so an agent can distinguish it without opening any schema.

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

Usage Guidelines5/5

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

Explicitly routes the agent: 'Use update_group to change an existing group and send_group_message to post in it.' The when-not condition is stated alongside the alternative, leaving nothing to inference.

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

create_pollA

Create a poll and send it to a contact or group. Use vote_poll to vote and terminate_poll to close it. question: the poll text; options: answer strings (at least 2, else an error); multi_select=true lets voters pick several answers (default false = single choice). Give recipient (E.164) for a DM or group_id (from list_groups) for a group; neither is an error. Contacts Signal's servers; not idempotent (each call sends a new poll); shares the 20-sends-per-minute rate limit; not saved to the local store. Returns {status: 'poll created', timestamp} — the timestamp (with your number as author) identifies the poll for vote_poll and terminate_poll.

ParametersJSON Schema
NameRequiredDescriptionDefault
optionsYesList of answer options (minimum 2 required)
group_idNoGroup ID for a group poll — provide this OR recipient
questionYesThe poll question text
recipientNoPhone number for a DM poll — provide this OR group_id
multi_selectNoAllow voters to select multiple options (default: false = single choice only)

TDQS

A4.9/5.0
Behavior5/5

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

Goes well beyond the annotations: it warns that each call contacts Signal's servers, is not idempotent, shares a 20-sends-per-minute rate limit, and is not saved to the local store. It also discloses the return shape {status, timestamp} and how the timestamp keys vote_poll/terminate_poll.

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

Conciseness4/5

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

Dense but front-loaded, leading with the action before branching into usage and parameter rules. Every clause carries information, though the packed single-paragraph form is slightly heavy.

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

Completeness5/5

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

No output schema exists, but the description supplies the return shape and the identity key needed for follow-up calls. Combined with rich parameter and behavioral detail, an agent has everything needed to invoke it correctly.

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 100%, yet the description adds real meaning: options must have at least 2 or it errors, multi_select=true enables multi-answer (default single), recipient must be E.164, group_id comes from list_groups, and supplying neither is an error. This compensates for constraints the schema cannot express.

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+resource ('Create a poll') plus its delivery scope ('send it to a contact or group'). It explicitly names the sibling tools vote_poll and terminate_poll, so an agent can distinguish the lifecycle stages without opening schemas.

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

Usage Guidelines5/5

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

Gives explicit routing ('Use vote_poll to vote and terminate_poll to close it') and states the selection rule for recipient (DM) vs group_id (group), including that providing neither is an error. Edge conditions are surfaced rather than left to inference.

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

delete_group_messageA
DestructiveIdempotent

Remote-delete (unsend) a message you sent to a group, removing it for all members on Signal 5.0+ clients. Use delete_message for DMs; admin_delete_message to delete another member's message as admin; delete_local_messages for local-only removal. group_id: from list_groups; target_timestamp: ms timestamp of your message (from the send_group_message result or get_conversation). Irreversible; older clients may silently ignore it; repeating it has no further effect. The local store copy is kept. Returns {status: 'deleted'}.

ParametersJSON Schema
NameRequiredDescriptionDefault
group_idYesGroup ID
target_timestampYesTimestamp of the message to delete

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already flag destructiveHint=true and idempotentHint=true, but the description adds real context beyond them: irreversibility, that older clients may silently ignore the delete, that repeating it has no further effect, and that the local store copy is retained. It also discloses the return shape ({status: 'deleted'}) since no output schema exists.

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?

Front-loaded with the core action, then routing, then parameter sourcing, then caveats and return value. Despite its length, every clause carries distinct information (version dependency, irreversibility, idempotency, local-copy retention) with no filler.

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

Completeness5/5

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

For a destructive mutation tool with no output schema, the description covers everything an agent needs: safety profile (already in annotations, reinforced here), irreversibility, client-compatibility caveat, idempotency, parameter provenance, and the return value. Nothing material is missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds provenance the schema lacks: group_id comes from list_groups, and target_timestamp is the ms timestamp of the caller's own message from send_group_message or get_conversation. That sourcing guidance exceeds what the terse schema descriptions ('Group ID', 'Timestamp of the message to delete') provide.

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 ('Remote-delete (unsend) a message you sent to a group') with precise scope ('removing it for all members on Signal 5.0+ clients'). It explicitly distinguishes itself from the three closest siblings (delete_message for DMs, admin_delete_message, delete_local_messages), so an agent can route correctly without opening any schema.

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

Usage Guidelines5/5

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

Gives explicit when-to-use-this vs alternatives: 'Use delete_message for DMs; admin_delete_message to delete another member's message as admin; delete_local_messages for local-only removal.' The selection condition for each alternative is named, leaving nothing to inference.

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

delete_local_messagesA
DestructiveIdempotent

Delete the locally stored messages of one conversation from signal-mcp's database. recipient (required): the contact's E.164 phone number or the group ID; your own number deletes only your note-to-self messages. Local only: nothing is unsent from Signal or removed from other devices; irreversible locally. Returns {deleted: count, status: 'deleted'} (0 if nothing matched). Use clear_local_store to wipe everything, prune_store to drop messages by age, delete_message to unsend in Signal.

ParametersJSON Schema
NameRequiredDescriptionDefault
recipientYesPhone number or group ID whose messages to delete

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already flag destructiveHint=true, idempotentHint=true and readOnlyHint=false, but the description adds genuinely new context: nothing is unsent from Signal or removed from other devices, changes are irreversible locally, and the return shape is {deleted, status} with 0 when nothing matched. This goes well beyond the annotation surface.

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

Conciseness4/5

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

Purpose is front-loaded in the first sentence, then recipient semantics, then local-only scope, then alternatives. Dense but every clause carries information; the parenthetical return note is slightly cramped but earns its place.

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

Completeness5/5

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

No output schema exists, yet the description supplies the return shape and the zero-match case, plus the destructive scope and alternatives. For a single-parameter destructive tool, nothing an agent needs is missing.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3, but the description adds real meaning the schema lacks: recipient accepts E.164 phone number or group ID, and using your own number deletes only note-to-self messages. That special-case behavior is not in the schema.

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

Purpose5/5

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

States a precise verb+resource+scope: 'Delete the locally stored messages of one conversation from signal-mcp's database.' The 'locally stored' qualifier immediately distinguishes it from Signal-side deletions, and the sibling routing makes the boundary explicit.

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

Usage Guidelines5/5

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

Explicitly names three alternatives and the condition that selects each: clear_local_store to wipe everything, prune_store to drop by age, delete_message to unsend in Signal. Nothing is left to inference about when to reach for this tool.

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

delete_messageA
DestructiveIdempotent

Remote-delete (unsend) a message you sent to one contact, removing it for everyone in the chat on Signal 5.0+ clients. Use delete_group_message for groups; delete_local_messages to remove messages only from the local store. Only your own messages can be deleted — you cannot delete what others sent. recipient: E.164 number of the contact; target_timestamp: ms timestamp of your message (from the send_message result or get_conversation). Irreversible; older clients may silently ignore it; repeating it has no further effect. The local store copy is kept. Returns {status: 'deleted'}.

ParametersJSON Schema
NameRequiredDescriptionDefault
recipientYesPhone number of the recipient
target_timestampYesTimestamp of the message to delete

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare destructive=true and idempotent=true, but the description goes well beyond them: irreversible, older clients may silently ignore it, repeating has no further effect, and the local store copy is retained. These are non-obvious behavioral traits an agent needs before invoking.

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 alternatives, then constraints, then return value. Dense but each clause carries information; the constraint list is slightly packed but nothing is redundant.

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

Completeness5/5

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

With no output schema, the description still reports the return shape ({status: 'deleted'}), covers irreversibility, idempotency, client-version caveats, and where to obtain the timestamp. Nothing needed to call it correctly is missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds real value: recipient is specified as an E.164 number and target_timestamp as a millisecond timestamp obtainable from the send_message result or get_conversation. That clarifies format and provenance beyond the schema's generic wording.

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

Purpose5/5

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

States a precise verb and resource ('Remote-delete (unsend) a message you sent to one contact') with explicit scope ('one contact'). It names the two sibling tools it is distinct from, so an agent can route correctly without opening any schema.

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

Usage Guidelines5/5

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

Gives explicit routing rules: use delete_group_message for groups and delete_local_messages for local-only removal. It also states the precondition that only your own messages can be deleted, which is exactly the when/when-not guidance needed.

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

edit_messageA
DestructiveIdempotent

Replace the text of a message you already sent (DM or group); recipients see the new text with an '(edited)' label. Use to fix typos or update information; use delete_message / delete_group_message to retract it instead, and send a new message to reach different people. Only the text changes — attachments, quotes and reactions stay. target_timestamp: ms timestamp of the original (from the send_* result or the message id in get_conversation). message: the new full text (no formatting conversion). Give recipient (E.164) for a DM or group_id (from list_groups) for a group; neither is an error. Signal only accepts edits of your own messages. Contacts Signal's servers and overwrites the stored body locally (the old text is not kept); repeating the same edit has no further effect. Returns {status, target_timestamp}.

ParametersJSON Schema
NameRequiredDescriptionDefault
messageYesNew message text to replace the original
group_idNoGroup ID for a group message edit
recipientNoPhone number for a DM message edit
target_timestampYesTimestamp of the message to edit (from get_conversation or send_message response)

TDQS

A4.8/5.0
Behavior5/5

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

Goes well beyond annotations: recipients see an '(edited)' label, only text changes while attachments/quotes/reactions stay, only your own messages can be edited, the stored body is overwritten locally and the old text is not kept, and repeating the same edit has no further effect. These details are consistent with destructiveHint=true and idempotentHint=true rather than contradicting them.

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

Conciseness4/5

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

Front-loads the core action and the '(edited)' consequence, then routes to alternatives before parameter details. It is dense and information-rich, though a couple of clauses (e.g. the returns note) could be tightened.

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

Completeness5/5

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

For a mutation tool with no output schema, it discloses the return shape ({status, target_timestamp}), the server round-trip, and the local-overwrite behavior. Combined with annotations covering the safety profile, nothing an agent needs to call it correctly is missing.

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

Parameters4/5

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

Schema coverage is already 100%, so the baseline is 3, but the description adds real meaning: target_timestamp provenance ('from the send_* result or the message id in get_conversation'), the 'no formatting conversion' constraint on message, and the E.164 / list_groups sourcing for recipient and group_id.

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

Purpose5/5

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

States a specific verb and resource with scope: 'Replace the text of a message you already sent (DM or group)'. It immediately distinguishes itself from send_message and delete_message, so an agent can pick it without opening the schema.

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

Usage Guidelines5/5

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

Explicitly names the situations to use it ('fix typos or update information') and the alternatives with their selection conditions: delete_message / delete_group_message to retract, and send a new message to reach different people. Nothing is left to inference.

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

export_messagesA
Read-onlyIdempotent

Export messages from signal-mcp's local store as one JSON or CSV string, for archiving or analysis. format: 'json' (default; full message objects with resolved sender_name/group_name, attachments and extras) or 'csv' (flat columns id, timestamp, sender, sender_name, recipient, group_id, group_name, body, quote_id, is_read). recipient (optional): limit to one conversation, an E.164 phone number or a group ID. since (optional, ISO 8601 datetime, e.g. '2026-01-01T00:00:00'): only messages at or after it; an invalid value returns an error. Read-only. Only messages already in the local store are included (run sync_desktop or receive_messages first). Returns {format, data}. Use get_conversation or search_messages to read messages interactively.

ParametersJSON Schema
NameRequiredDescriptionDefault
sinceNoOnly include messages at or after this ISO datetime
formatNoOutput format (default: json)
recipientNoExport only this conversation (phone number or group ID)

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive, so the burden is lightened, and the description still adds real behavior: store-scoped data only, a prerequisite sync step, error on an invalid 'since', and the return shape {format, data}. It omits anything about volume/performance or limits on large exports, which keeps it short of a 5.

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

Conciseness4/5

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

Front-loaded with purpose, then format, optional params, caveats, return shape, and the alternative tool — a logical order with no filler sentences. It is somewhat dense and re-explains parameter meanings already present in the schema, which costs a little economy.

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

Completeness4/5

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

With no output schema, the description compensates by naming the return object and describing the contents of each format, and it covers the prerequisite and error case. Minor gaps remain around export size/limits and whether CSV escaping is handled, but nothing essential for calling it correctly is missing.

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?

Despite 100% schema coverage, the description adds genuine semantics the schema lacks: what 'json' actually contains (full message objects with resolved sender_name/group_name, attachments, extras), the exact CSV column set, the E.164/group-ID constraint on recipient, an ISO 8601 example for since, and the invalid-value error behavior.

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+resource+output form: export messages from signal-mcp's local store as a single JSON or CSV string. It immediately signals how it differs from read-oriented siblings by naming get_conversation and search_messages as the interactive alternatives.

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 context (archiving or analysis, bulk single-string output) and an explicit prerequisite: only messages already in the local store are included, so run sync_desktop or receive_messages first. It routes the agent to get_conversation/search_messages for interactive reading, though it never states an explicit 'do not use this for X' exclusion.

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

find_contactA
Read-onlyIdempotent

Find contacts whose number, name, given/family name, nickname or username contains query (case-insensitive substring; required). Use it to resolve a name to an E.164 number before send_message, or to check that a contact exists; use list_contacts instead to list everyone or filter by blocked status. all_recipients (default false) also searches people outside your address book, e.g. group members known only by their profile name. Reads the local contact store only. Returns a list (possibly empty) of contact objects with number, uuid, name, given_name, family_name, about, blocked and display_name.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesCase-insensitive fragment of a name, nickname, username or phone number
all_recipientsNoAlso include recipients that are not in your address book (e.g. members of your groups), with their profile names

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint=false and destructiveHint=false. The description adds genuinely new context: that it reads the local contact store only, that the result may be empty, and it enumerates the returned fields — behavior not derivable from the annotations. It stops short of discussing pagination or ordering, so not a 5.

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

Conciseness4/5

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

Dense but front-loaded: the matching rule and the query semantics come first, then routing, then the return shape. Every sentence carries information, though the run-on construction makes it slightly heavier than it needs to be.

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

Completeness5/5

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

With no output schema, the description compensates by enumerating the returned contact object fields and noting the list may be empty. Combined with the sibling routing and the local-store scope, an agent has everything needed to call and interpret this tool.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description goes further by stating query is required and case-insensitive, and by explaining what all_recipients=false means in practice (group members known only by profile name). That example adds real meaning beyond the schema's phrasing.

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 (find) and resource (contacts) plus the exact matching fields (number, name, given/family name, nickname, username) and match semantics (case-insensitive substring). It also names the sibling it is not (list_contacts), so an agent can distinguish it without opening either schema.

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

Usage Guidelines5/5

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

Explicitly states when to use it (resolve a name to an E.164 number before send_message, or verify a contact exists) and when to use the alternative instead (list_contacts for listing everyone or filtering by blocked status). Both the positive and negative routing conditions are given.

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

finish_change_numberA

Step 2 of moving this Signal account to a new phone number: submits the verification code and completes the change. Call start_change_number first; without it there is no code to verify. number (required): the same new E.164 number given to start_change_number; verification_code (required): the 6-digit code received by SMS or voice call; pin (optional): your Registration Lock PIN, needed only if one is set (see set_pin). Primary device only: on a linked signal-cli setup it fails with 'This command doesn't work on linked devices'. On success the real account is moved to the new number; this cannot be undone except by another change-number round. A wrong pin fails with the number of tries remaining. Returns {status: 'number changed', number}.

ParametersJSON Schema
NameRequiredDescriptionDefault
pinNoRegistration lock PIN (required if the account has a PIN set)
numberYesThe new phone number in E.164 format
verification_codeYes6-digit verification code from SMS/voice

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only supply generic hints (readOnlyHint=false, idempotentHint=false, openWorldHint=true). The description adds concrete behavior beyond them: primary-device-only restriction with the literal failure message, irreversibility ('cannot be undone except by another change-number round'), and error semantics for a wrong PIN ('fails with the number of tries remaining').

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 step-2 framing and prerequisite are front-loaded, and each sentence carries a distinct fact (prereq, params, device restriction, consequence, error behavior, return value). It is dense rather than padded, though the run-on single paragraph could be split for faster scanning.

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

Completeness5/5

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

No output schema exists, yet the description documents the return value ({status: 'number changed', number}), the prerequisite, the side effect, and the failure modes. For a 3-param, irreversible multi-step tool this covers everything an agent needs before calling.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning the schema lacks: 'number' must be the same value passed to start_change_number, and 'pin' is conditional on a Registration Lock being set. It stops short of adding format nuances beyond E.164, which the schema already states.

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 (submits the verification code) plus the exact scope: it is step 2 of moving this Signal account to a new phone number. It explicitly positions itself relative to the sibling start_change_number ('Call start_change_number first'), so an agent can separate the two-step flow without opening either schema.

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

Usage Guidelines5/5

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

Gives an explicit prerequisite ('without it there is no code to verify') and names the alternative path for the optional PIN parameter ('needed only if one is set (see set_pin)'). It also states the when-not condition: primary device only, failing on linked signal-cli setups.

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

get_attachmentA
Idempotent

Look up one received attachment and make sure it is saved locally. filename (required): a filename from list_attachments, or a signal-cli attachment id from a message's attachments; path components such as '../' are rejected. If the file is not in ~/Downloads/signal-attachments, it is copied there from signal-cli's own attachment store (only attachments signal-cli already downloaded; otherwise 'Attachment not found'). Returns {filename, path, size (bytes), modified (ISO datetime)}: metadata and the local path, not the file content. Nothing is sent to Signal. Use send_attachment or send_group_attachment to send a file.

ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYesAttachment filename (from list_attachments) or signal-cli attachment id

TDQS

A4.6/5.0
Behavior5/5

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

Adds substantial context beyond the annotations: it explains the local copy into ~/Downloads/signal-attachments, that only attachments signal-cli already downloaded are available, the exact 'Attachment not found' failure, and that nothing is sent to Signal. This reconciles readOnlyHint=false with destructiveHint=false and idempotentHint=true meaningfully.

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

Conciseness4/5

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

Dense but front-loaded: the action and the required parameter come first, then resolution behavior, then return shape, then routing to siblings. Slightly long, though nearly every sentence carries distinct operational detail.

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

Completeness5/5

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

With no output schema, the description compensates by enumerating the return object ({filename, path, size, modified}) and clarifying it returns metadata rather than file content. For a single-parameter, non-destructive read/copy tool this is complete.

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

Parameters4/5

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

Schema coverage is 100% so the baseline is 3, but the description adds real semantics: accepted formats (filename or signal-cli attachment id) and the security constraint that path components such as '../' are rejected. That is genuine information not present in the schema.

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

Purpose5/5

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

States a specific verb and resource ('Look up one received attachment and make sure it is saved locally'), and distinguishes itself from siblings by naming list_attachments as the source of the identifier and send_attachment/send_group_attachment as the senders. An agent can route correctly without opening any schema.

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 context and an explicit alternative ('Use send_attachment or send_group_attachment to send a file') plus where the filename comes from (list_attachments or a message's attachments). It does not spell out when-not to use it for other attachment operations, so it falls just short of the top band.

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

get_avatarA
Read-onlyIdempotent

Return a contact's or group's avatar image as base64, from the copy signal-cli has stored. identifier (required): an E.164 phone number for a contact, or a group id from list_groups for a group (anything that is not a full E.164 number is treated as a group id). Returns identifier, base64 (decode to get the JPEG/PNG bytes) and has_avatar; fails with 'Could not find avatar' when none is stored. Use update_profile with avatar_path to set your own photo, update_group with avatar for a group's.

ParametersJSON Schema
NameRequiredDescriptionDefault
identifierYesPhone number (E.164) for a contact or group ID for a group

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the readOnly/idempotent annotations, it discloses the source (copy signal-cli has stored), the return shape (identifier, base64, has_avatar), decode format, and the exact failure case 'Could not find avatar'. This is rich context that annotations alone would not provide.

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 with the core action and avoids filler. It is a dense single paragraph, but every sentence contributes useful information; minor structural improvement could make the return and failure details easier to scan.

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

Completeness5/5

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

There is no output schema, so the description carries the burden of explaining return values, and it does so thoroughly with identifier, base64, and has_avatar. It also covers the failure case, identifier types, and related update tools, making it complete for this one-parameter read tool.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds useful meaning: identifier is required, E.164 for contacts, group id from list_groups for groups, and anything not full E.164 is treated as a group id. That heuristic parsing rule goes beyond the schema description.

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

Purpose5/5

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

The description states a specific verb and resource: return a contact's or group's avatar image as base64. It distinguishes the contact vs. group identifier rules and names related setters (update_profile, update_group), so an agent can identify the tool 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 Guidelines4/5

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

It gives concrete identifier conditions and points to update_profile/update_group for setting avatars, which helps route the agent. It does not explicitly state when not to use this tool or name a retrieval alternative, so it has clear context but lacks full exclusion guidance.

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

get_conversationA
Idempotent

Read the message history of one conversation from the local store (no Signal server call). Use list_conversations to find conversations, search_messages to find text across all chats, get_unread for only new messages. recipient: E.164 number for a DM or a group_id (from list_groups). limit: max messages (default 50, clamped 1-500); offset: skip the newest N for paging back (default 0); since: only messages at or after this ISO datetime (e.g. 2024-01-01T00:00:00; invalid values return an error). Side effect: incoming messages returned are marked read in the local store only — no read receipt is sent (use send_read_receipt). Returns {messages (oldest first; id, sender, sender_name, body, timestamp, attachments, quote_id, reactions, is_read …), total, has_more, limit, offset}. Timestamps are milliseconds: a message's id in get_conversation is its timestamp (sent messages: sent__).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax messages to return (default 50, clamped 1-500)
sinceNoOnly messages after this ISO datetime (e.g. 2024-01-01T00:00:00)
offsetNoNumber of newest messages to skip for pagination (default: 0)
recipientYesE.164 phone number for a DM, or group ID (from list_groups)

TDQS

A4.4/5.0
Behavior3/5

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

Annotations declare readOnlyHint=false and idempotentHint=true, which is the non-obvious part here. The description explains the side effect well (incoming messages marked read in the local store only, no receipt sent) and that no server call is made. However the marking-read behavior IS the reason readOnlyHint is false, so the description mostly elaborates a trait the annotations already signal, keeping this at a solid 3.

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

Conciseness4/5

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

Purpose is front-loaded and every sentence carries information (alternatives, params, side effect, return shape). It is dense and reads as a single packed block, but nothing is redundant.

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

Completeness5/5

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

With no output schema, the description supplies the return shape (messages, total, has_more, limit, offset) and even timestamp/id semantics. Combined with full param and side-effect coverage, nothing needed to call it correctly is missing.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3, but the description adds genuine meaning: recipient accepts E.164 or group_id, offset is described as 'skip the newest N for paging back', and since notes invalid values return an error. These add semantics beyond the schema text.

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+resource ('Read the message history of one conversation') with clear scope ('from the local store, no Signal server call'). It explicitly distinguishes itself from list_conversations, search_messages, and get_unread, so an agent can route without opening any schema.

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

Usage Guidelines5/5

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

Names three alternative siblings with the exact condition that selects each (find conversations vs. search across chats vs. only unread). It also documents when to use send_read_receipt instead of relying on this tool for read receipts.

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

get_own_numberA
Read-onlyIdempotent

Return this server's own Signal account number as {number} (E.164, e.g. +4915112345678). Local lookup: no network call, no daemon needed, no side effects. Use it to know which messages are your own (sender == number) or to address send_note_to_self; use list_accounts instead to see every account registered in signal-cli on this machine.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive, and openWorld=false, so the safety profile is covered. The description still adds beyond that: it characterizes the operation as a purely local lookup with no network call and no daemon dependency, plus the value's format. It loses the top mark only because 'no side effects' restates destructiveHint=false.

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?

Front-loaded with the core answer, then format, then behavioral traits, then routing to siblings. Every clause (E.164 example, local-lookup guarantee, two use cases, one exclusion) earns its place with no filler.

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

Completeness5/5

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

For a no-parameter, no-output-schema tool, the description supplies the missing return contract itself ({number} in E.164), the operational cost model (local, no network), and sibling routing. Nothing an agent needs to invoke it correctly is absent.

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?

The tool takes zero parameters, so there is nothing for the description to disambiguate; per the baseline for 0-param tools this lands at 4. The description correctly adds no parameter noise and instead spends its words on the return value.

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+resource ('Return this server's own Signal account number') and pins the exact return format with an E.164 example. It explicitly distinguishes itself from the closest sibling, list_accounts, so an agent can tell them apart without opening either schema.

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

Usage Guidelines5/5

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

Names two concrete use cases (knowing which messages are your own via sender == number, and addressing send_note_to_self) and an exclusion with the alternative to pick instead (list_accounts). This is the explicit when/when-not/alternative pattern.

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

get_profileA
Read-onlyIdempotent

Check one phone number against Signal's servers and return what that lookup provides. number (required, E.164). Returns a contact object whose number and uuid (the Signal account id; null if the number is not registered) are filled; the lookup carries no profile data, so name, given_name, family_name and about come back null. For a contact's profile name and about text use find_contact or list_contacts with all_recipients=true; for their photo use get_avatar; to check many numbers at once use get_user_status. To change your own profile use update_profile.

ParametersJSON Schema
NameRequiredDescriptionDefault
numberYesPhone number in E.164 format

TDQS

A4.7/5.0
Behavior5/5

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

Annotations cover the safety profile (readOnly, idempotent, openWorld, non-destructive), and the description goes well beyond them: it discloses that the lookup carries no profile data, that name/given_name/family_name/about always return null, and that uuid is null when the number is unregistered. That is exactly the non-obvious behavior an agent needs to avoid misinterpreting the response.

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?

Four short sentences, each earning its place: purpose and return shape first, then a single routing sentence covering four alternatives. Zero filler and the most decision-relevant fact (null profile fields) is front-loaded.

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

Completeness5/5

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

No output schema exists, so the description carries the return contract itself — contact object with number/uuid, null uuid for unregistered numbers, and null profile fields — plus a full routing map to alternatives. Nothing an agent needs to call this correctly is missing.

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

Parameters3/5

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

Schema coverage is 100% and the single parameter is already documented as E.164 in the schema; the description merely restates '(required, E.164)'. With the schema doing the work and only one param, baseline 3 is appropriate — no additional format or edge-case semantics are added.

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 (check) and resource (one phone number against Signal's servers) and immediately clarifies the scope: a lookup, not a profile fetch. It explicitly distinguishes itself from find_contact/list_contacts/get_avatar/get_user_status, so an agent can pick correctly without opening any schema.

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

Usage Guidelines5/5

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

Names four concrete alternatives with the exact condition that selects each: find_contact or list_contacts with all_recipients=true for profile name/about, get_avatar for photos, get_user_status for bulk checks, update_profile for editing your own profile. Explicit when-to-use and when-not-to-use routing.

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

get_stickerA
Read-onlyIdempotent

Fetch one sticker image from an installed pack as base64. pack_id (required, hex string) and sticker_id (required, integer) come from list_sticker_packs (packId and stickers[].id) or add_sticker_pack. Read-only. Returns {base64}; the image format is the sticker's contentType from list_sticker_packs (usually image/webp). Use send_sticker or send_group_sticker to send it instead of downloading it.

ParametersJSON Schema
NameRequiredDescriptionDefault
pack_idYesSticker pack ID (hex string from list_sticker_packs)
sticker_idYesSticker ID within the pack

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint/idempotentHint/destructiveHint, so the 'Read-only' sentence is partly redundant, but the description earns its keep by disclosing the return payload ({base64}) and that the image format follows the sticker's contentType, usually image/webp. It does not discuss size limits or failure modes for missing sticker IDs.

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?

Three sentences, front-loaded with the core action and result, then provenance, then the alternative tool. The '(required, hex string)' restatement and 'Read-only' repeat what the schema and annotations already carry, a small amount of waste.

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

Completeness5/5

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

No output schema exists, yet the description compensates by naming the exact return shape and format, plus the ID sources. For a two-parameter read tool, an agent has everything needed to invoke it correctly.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds real provenance detail beyond the schema: pack_id is a hex string from list_sticker_packs' packId field, and sticker_id maps to stickers[].id. That helps an agent construct valid calls rather than guess.

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 ('Fetch one sticker image from an installed pack') and even names the return encoding (base64). This clearly separates it from the sibling send_sticker / send_group_sticker tools that deliver rather than fetch.

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

Usage Guidelines5/5

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

Explicitly routes the agent: 'Use send_sticker or send_group_sticker to send it instead of downloading it,' which is exactly the when-not guidance needed given the adjacent send tools. It also states where both IDs must come from (list_sticker_packs or add_sticker_pack).

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

get_unreadA

Return new unread incoming messages across all conversations — the default way to check for new messages. If the background service (signal-mcp install-service) is running it reads the local store; otherwise it first polls signal-cli (at most once per 30 s) and adds a _warning suggesting the service. Use get_conversation for a chat's full history, list_conversations for an inbox overview. limit: max messages (default 50, clamped 1-500); the newest are kept. Side effect: returned messages are marked read in the local store only (no read receipt — use send_read_receipt; mark_as_unread to undo). Returns {messages (oldest first; id, sender, sender_name, group_id, group_name, body, timestamp, attachments …), has_more}; if has_more is true call again with the same limit to get the next batch.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax messages to return (default: 50)

TDQS

A5/5.0
Behavior5/5

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

Annotations already indicate the operation is not read-only, not destructive, not idempotent, and open-world. The description goes further by disclosing the local-store read-marking side effect, the absence of a read receipt, the background service behavior, and the at-most-once-per-30s polling fallback. This gives an agent unusually rich operational context.

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

Conciseness5/5

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

The description is dense but front-loaded, opening with the tool's primary purpose before detailing side effects, alternatives, parameter behavior, and pagination. Every sentence carries operational value, especially given the absence of an output schema.

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

Completeness5/5

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

With no output schema, the description fully compensates by describing the return object shape, key fields, ordering, and has_more pagination. It also covers side effects, alternative tools, and the optional limit's behavior, leaving no critical invocation gap.

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?

The single limit parameter is well covered by the schema, but the description adds important semantics missing there: the value is clamped to 1-500 and the newest messages are kept when more exist. That directly affects how an agent should invoke the tool and interpret results.

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

Purpose5/5

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

The description states a specific verb and resource: returns new unread incoming messages across all conversations. It immediately distinguishes this tool as the default way to check for new messages, helping an agent separate it from sibling tools such as get_conversation and list_conversations.

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

Usage Guidelines5/5

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

It explicitly says when to use this tool (default check for new messages) and names alternatives for related tasks: get_conversation for full chat history and list_conversations for an inbox overview. It also documents the side effect and points to send_read_receipt and mark_as_unread for receipt/undo behavior.

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

get_user_statusA
Read-onlyIdempotent

Check whether phone numbers and/or usernames are registered on Signal, in one batch query to Signal's servers. recipients: list of E.164 phone numbers; usernames: list of Signal usernames or username links; at least one of the two is required. Returns one entry per input with recipient, number or username, uuid (null if not registered) and isRegistered. Use it before messaging an unknown number; numbers that hide their discoverability can show as unregistered. For a contact's name or details use find_contact or get_profile.

ParametersJSON Schema
NameRequiredDescriptionDefault
usernamesNoList of Signal usernames or username links to check
recipientsNoList of phone numbers (E.164) to check

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered. The description adds value beyond that by disclosing the return shape (one entry per input with recipient, number/username, uuid null when unregistered, isRegistered) and the discoverability caveat — both absent from annotations. It stops short of describing pagination or rate limiting, hence not a 5.

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

Conciseness5/5

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

Three dense sentences with zero filler: purpose and batching first, parameter formats and the at-least-one constraint second, return shape and usage caveat third. Every sentence carries distinct information and the purpose is front-loaded.

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

Completeness5/5

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

There is no output schema, so the description carries the burden of explaining return values and does so (uuid null when unregistered, isRegistered). Combined with the required-parameter constraint, the alternatives for contact lookup, and the discoverability caveat, an agent has everything needed to call and interpret this tool.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3, but the description adds meaning the schema does not encode: it restates the formats (E.164 for recipients, usernames or username links) and states the cross-parameter constraint 'at least one of the two is required', which the schema cannot express since required is empty.

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 ('Check whether phone numbers and/or usernames are registered on Signal') plus the scope ('in one batch query to Signal's servers'), and explicitly routes away from find_contact/get_profile for other needs. An agent can distinguish it from list_contacts or get_profile without opening any schema.

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

Usage Guidelines5/5

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

Gives an explicit trigger ('Use it before messaging an unknown number') and names the alternatives for adjacent needs ('For a contact's name or details use find_contact or get_profile'). It also warns about a false-negative case (numbers that hide discoverability), which is exactly the kind of when-not guidance an agent needs.

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

get_webhookA
Read-onlyIdempotent

Return the webhook URL in effect as {url}, or {url: null} if none is configured. No parameters. The SIGNAL_MCP_WEBHOOK environment variable wins over the URL saved with set_webhook. Read-only, local only. Use set_webhook to change or clear it.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint=false and destructiveHint=false, so the safety profile is covered. The description adds genuinely non-obvious behavior: the SIGNAL_MCP_WEBHOOK environment variable takes precedence over the stored URL, which directly affects how the returned value should be interpreted. It does not cover error or failure behavior, so it falls short of fully rich disclosure.

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

Conciseness5/5

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

Three short sentences with zero filler, and the return shape is front-loaded before the precedence rule and the sibling pointer. Every sentence carries distinct information.

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

Completeness5/5

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

With no output schema, the description supplies the return format ({url} or {url: null}), the precedence rule governing the value, and the routing to the mutating alternative. Nothing an agent needs to call and interpret this correctly is missing.

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?

The tool takes zero parameters, which is the baseline-4 case. The description confirms this explicitly ('No parameters.'), matching the empty schema with no ambiguity.

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 ('Return the webhook URL in effect') and even specifies the exact return shape ({url} or {url: null}). It names its counterpart sibling, set_webhook, so an agent can distinguish read from write without opening either schema.

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

Usage Guidelines5/5

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

Explicitly names the alternative ('Use set_webhook to change or clear it') and the condition that selects it, plus notes there are no parameters. An agent knows exactly when to call this versus the mutating sibling.

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

import_desktopA
Idempotent

Import the full message history from Signal Desktop on this machine into signal-mcp's local store, so get_conversation, search_messages and export_messages can see older messages. No parameters. Reads Signal Desktop's encrypted database, which needs sqlcipher installed and the database key: on macOS read from the Keychain ('Signal Safe Storage', may prompt for access), on Linux via secret-tool (libsecret / GNOME Keyring). Signal Desktop must be installed and opened at least once. Only writes to the local store; nothing is sent to Signal. Already stored messages are skipped, so re-running is safe but slow. Only one import can run at a time. Returns {imported, skipped, total, max_ts_ms, platform, source}. Use sync_desktop for later updates; it only reads messages newer than the last sync.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.8/5.0
Behavior5/5

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

Goes well past the annotations (idempotentHint=true, destructiveHint=false, openWorldHint=false). It discloses what is read (encrypted local DB, key via macOS Keychain or Linux secret-tool, possible access prompt), what is written (local store only, nothing sent to Signal), idempotency semantics ('already stored messages are skipped, re-running is safe but slow'), and a concurrency constraint ('only one import can run at a time').

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 purpose and benefit, then prerequisites, then safety/idempotency/return shape. Every sentence carries operational information, but the description is dense and runs long for a zero-param tool; a minor trim would tighten it.

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

Completeness5/5

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

With no output schema, the description supplies the return shape ({imported, skipped, total, max_ts_ms, platform, source}). Combined with prerequisites, safety guarantees, idempotency, and the sync_desktop alternative, an agent has everything needed to call and interpret this tool.

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

Parameters4/5

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

Zero parameters, so the baseline is 4. The description correctly states 'No parameters' and adds no misleading param info, though there is nothing further to clarify beyond confirming the tool takes no input.

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+resource+scope: 'Import the full message history from Signal Desktop on this machine into signal-mcp's local store.' It also names the concrete benefit (older messages visible to get_conversation, search_messages, export_messages) and explicitly contrasts with the sibling sync_desktop, so an agent can pick the right tool without opening a schema.

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

Usage Guidelines5/5

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

Gives explicit routing: 'Use sync_desktop for later updates; it only reads messages newer than the last sync.' Prerequisites are spelled out (Signal Desktop installed and opened at least once, sqlcipher installed, database key available), which tells the agent exactly when this call will and won't work.

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

join_groupA
Idempotent

Join a Signal group from an invite link. uri (required) is the link, https://signal.group/#... Use this for groups you are not in; for groups you already belong to use list_groups. Contacts Signal's servers and notifies the group. If the group requires admin approval you become a requesting member and the result has onlyRequested=true (or the call fails with 'Pending admin approval'); an invalid or reset link fails with 'Group link is invalid'. Returns status, groupId, timestamp and send results; use the groupId as group_id for send_group_message.

ParametersJSON Schema
NameRequiredDescriptionDefault
uriYesGroup invite link starting with https://signal.group/#

TDQS

A4.7/5.0
Behavior5/5

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

Goes well beyond the annotations (readOnlyHint=false, openWorldHint=true, idempotentHint=true, destructiveHint=false) by disclosing the network side effect (contacts Signal's servers, notifies the group), the admin-approval path (requesting member, onlyRequested=true, or the 'Pending admin approval' failure), the invalid/reset-link failure text, and the return fields. This is exactly the behavioral context annotations cannot carry.

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

Conciseness5/5

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

Front-loads the action and required parameter, then layers usage routing, side effects, failure modes, and return handling. Every sentence carries distinct information and no sentence is filler, despite the overall length.

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

Completeness5/5

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

With no output schema, the description compensates by naming the returned fields (status, groupId, timestamp, send results) and the actionable failure strings. Combined with the routing guidance and side-effect disclosure, nothing an agent needs to call this correctly is missing.

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

Parameters3/5

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

Only one parameter and schema coverage is 100%; the schema already documents uri as 'Group invite link starting with https://signal.group/#'. The description restates the same format with an example, adding little meaning beyond the schema, so the baseline 3 applies.

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

Purpose5/5

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

States a specific verb+resource ('Join a Signal group from an invite link') and immediately distinguishes the case it serves from the alternative ('groups you are not in' vs list_groups). An agent can route between join_group, create_group, and list_groups without opening a schema.

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

Usage Guidelines5/5

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

Explicitly says when to use it ('groups you are not in') and names the alternative for the other case (list_groups). It also tells the agent where to go next after success, using the returned groupId as group_id for send_group_message.

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

leave_groupA
DestructiveIdempotent

Leave a Signal group yourself: sends a quit message to all members and removes you from the member list; the group continues for everyone else. To end the group for all members use terminate_group instead. group_id (required, from list_groups). admins: E.164 numbers of members to promote first — if you are the group's ONLY admin you must name one, otherwise signal-cli refuses. delete (default false): also delete the group's local data after leaving. You can only come back by being re-added or via an invite link. Returns status and group_id.

ParametersJSON Schema
NameRequiredDescriptionDefault
adminsNoMembers to make admin before leaving — required if you are the only admin
deleteNoAlso delete all local group data after leaving
group_idYesGroup ID to leave (get from list_groups)

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare destructiveHint and idempotentHint, but the description adds far more: a quit message is sent to all members, you are removed from the member list, the group survives for others, naming an admin is mandatory when you are the sole admin, and the irreversible re-entry constraint (re-added or invite link). This is rich context well beyond the structured fields.

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

Conciseness4/5

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

Purpose and the sibling alternative are front-loaded in the first sentence, followed by parameters and the return value. Dense but every clause carries information; only marginal tightening is possible.

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

Completeness5/5

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

No output schema exists, yet the description states the return value ('status and group_id'), covers all three parameters including defaults, and discloses the admin-promotion prerequisite and re-entry consequences. Complete for an agent to invoke correctly.

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

Parameters4/5

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

Schema coverage is 100%, so baseline would be 3, but the description goes further by giving the 'delete' default (false) and the consequence of setting it, which the schema does not state, and reinforces the group_id provenance. It slightly exceeds what the schema already provides.

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

Purpose5/5

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

States a specific verb and resource ('Leave a Signal group yourself') and precisely distinguishes the scope from its closest sibling by naming terminate_group as the tool for ending the group for everyone. An agent can select between them without opening either schema.

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

Usage Guidelines5/5

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

Explicitly names the alternative (terminate_group) and the condition that selects it, plus a hard prerequisite ('if you are the group's ONLY admin you must name one, otherwise signal-cli refuses'). When-to-use, when-not-to-use, and the failure mode are all covered.

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

list_accountsA
Read-onlyIdempotent

List every Signal account registered in signal-cli on this machine. Returns a JSON array of E.164 phone numbers (e.g. ["+4915112345678"]); no registration status or other fields. Read-only, asks the running signal-cli daemon. Most setups have exactly one account. Use get_own_number instead to get the single account this server sends and receives as.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

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

The annotations already carry the safety profile (readOnlyHint, idempotentHint, destructiveHint=false, openWorldHint=false), and the description goes well beyond them by disclosing the exact return shape (JSON array of E.164 numbers only, no registration status), the fact that it queries the running signal-cli daemon, and the common case of a single account. That is substantive behavioral context an agent needs.

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

Conciseness5/5

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

Three short sentences, front-loaded with what it returns, then constraints, then the sibling routing. Nothing redundant; every clause carries information.

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

Completeness5/5

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

No output schema exists, so the description properly compensates by specifying the return type and its exact contents, plus the daemon dependency and typical cardinality. Nothing an agent needs to invoke it correctly is missing.

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?

There are zero parameters and schema coverage is 100%, so the baseline of 4 applies; the description correctly makes no attempt to invent parameters and confirms the call takes no arguments.

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 (List) and resource (Signal accounts registered in signal-cli on this machine), and explicitly distinguishes itself from get_own_number, the closest sibling. An agent can tell exactly which of the 70+ siblings this is without opening a schema.

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

Usage Guidelines5/5

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

Names the alternative tool (get_own_number) and the condition that selects it: this tool enumerates all registered accounts, while get_own_number returns the single sending/receiving identity. That is explicit when-to-use/when-not routing.

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

list_attachmentsA
Read-onlyIdempotent

List the attachment files saved in the local attachments folder (~/Downloads/signal-attachments). No parameters. Returns an array of {filename, path, size (bytes), modified (ISO datetime)}, sorted by filename; empty if the folder does not exist. Read-only and local; nothing is downloaded. Pass a filename to get_attachment for its details. Attachments of incoming messages land here when messages are received (receive_messages or the background service).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare readOnlyHint, idempotentHint and openWorldHint=false, and the description reinforces this with 'Read-only and local; nothing is downloaded.' It goes further by disclosing the empty-folder behavior and where attachments originate, which annotations cannot express.

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

Conciseness4/5

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

Front-loaded with the core action and scope, then return shape, then routing. Dense with semicolon-separated facts, but every clause carries information an agent needs; slightly long but not padded.

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

Completeness5/5

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

With no output schema, the description supplies the return structure ({filename, path, size, modified}, sorted by filename, empty when the folder is missing), which is exactly what is needed. Nothing required to call it correctly is missing.

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?

Zero parameters, so the baseline is 4. The description still explicitly states 'No parameters,' removing any doubt about whether a path or filter argument exists.

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 (list attachment files) plus the exact scope (the local ~/Downloads/signal-attachments folder). It is clearly distinguishable from siblings get_attachment (details for one file) and send_attachment (uploading), which it references by name.

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?

Routes the agent explicitly: 'Pass a filename to get_attachment for its details,' and clarifies the relationship to receive_messages and the background service that populates the folder. It lacks an explicit when-not-to-use statement, but the context is unambiguous.

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

list_contactsA
Read-onlyIdempotent

List the contacts in signal-cli's local contact store (no network call). Use it to browse or audit contacts; to look up one person's number by name, find_contact is the shorter call. Parameters: search (optional) keeps only contacts whose number, name, given/family name, nickname or username contains it (case-insensitive); all_recipients (default false) also includes people not in your address book, e.g. members of your groups; blocked=true returns only blocked contacts, false only unblocked, omitted all. Returns a list of objects with number (E.164), uuid, name, given_name, family_name, about, blocked, display_name, plus username, nick_name, note, has_avatar, message_expiration_time etc. when set.

ParametersJSON Schema
NameRequiredDescriptionDefault
searchNoFilter contacts by name or number (case-insensitive substring match)
blockedNotrue = only blocked contacts, false = only unblocked (omit for all)
all_recipientsNoAlso include recipients that are not in your address book (e.g. members of your groups), with their profile names

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so safety is covered. The description adds genuinely new context: it operates on the local store with 'no network call', which sharpens the openWorld hint into an actionable fact. It does not discuss result size or ordering, which is a minor gap.

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

Conciseness4/5

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

Front-loaded with the core purpose and the sibling routing, then parameters, then return shape. Dense and mostly waste-free, though the return-field enumeration runs long as one comma-separated tail.

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

Completeness5/5

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

No output schema exists, and the description compensates by naming the returned fields (number, uuid, name, given_name, blocked, etc.). With 100% parameter coverage plus return shape plus sibling routing, an agent has everything needed to call this correctly.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3, but the description goes beyond the schema: the schema says search matches 'name or number' while the description enumerates number, name, given/family name, nickname and username. It also spells out the tri-state blocked semantics and gives a concrete example for all_recipients.

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 (list contacts in signal-cli's local contact store) and immediately distinguishes itself from the sibling find_contact, which does the narrower single-person lookup. An agent can select between the two without opening either schema.

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

Usage Guidelines5/5

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

Explicit when-to-use ('browse or audit contacts') and names the alternative with the condition that selects it ('to look up one person's number by name, find_contact is the shorter call'). Nothing is left to inference.

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

list_conversationsA
Read-onlyIdempotent

List every conversation (direct and group) in the local store, most recent first — an inbox overview. Takes no parameters. Use get_conversation to read one, get_unread for only new messages, search_messages to find text. Reads only locally stored messages (no Signal server call; nothing marked read); names come from the cached signal-cli contacts and groups. Returns a list of {id (E.164 number or group_id — pass to get_conversation), type ('direct' | 'group'), name, last_message, last_message_at (ISO), message_count, unread_count}.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, non-openWorld), and the description adds substantial context beyond them: it reads only locally stored messages, makes no Signal server call, marks nothing as read, and names come from the cached signal-cli contacts/groups. This is exactly the extra behavioral disclosure that structured fields cannot convey.

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

Conciseness5/5

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

Front-loaded with purpose and scope, then alternatives, then behavioral caveats, then the return shape. Despite being dense, every sentence carries actionable information with no filler.

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

Completeness5/5

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

No output schema exists, so the description compensates by enumerating the full return shape (id, type, name, last_message, last_message_at, message_count, unread_count) and even explains how to pass the id onward. Nothing an agent needs to call and consume this tool correctly is missing.

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

Parameters4/5

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

With zero parameters the baseline is 4; the description confirms 'Takes no parameters,' which is consistent with the empty schema. There is no further parameter meaning to add.

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 (List) and resource (every conversation, direct and group) with scope ('in the local store, most recent first — an inbox overview'). It clearly differentiates itself from sibling readers like get_conversation, get_unread, and search_messages.

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

Usage Guidelines5/5

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

Explicitly routes the agent to alternatives with conditions: 'Use get_conversation to read one, get_unread for only new messages, search_messages to find text.' Nothing is left to inference about when to pick this tool versus its neighbors.

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

list_devicesA
Read-onlyIdempotent

List all devices linked to your Signal account, queried from Signal's servers. Takes no parameters. Returns entries with id, name, createdTimestamp and lastSeenTimestamp (epoch ms); device id 1 is the primary phone. Use it to audit which devices have access, or to get the device id for update_device (rename) or remove_device (unlink).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered. The description adds genuine context beyond them: the query is a server round-trip (not a local cache read) and it spells out the returned fields, which matters because no output schema exists.

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

Conciseness5/5

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

Three tight sentences: what it does, the shape of the result, then when to use it. The routing hint to update_device/remove_device is front-loaded at the end where it is most actionable, and no sentence is filler.

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

Completeness5/5

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

For a parameterless read tool with no output schema, the description supplies exactly what is missing: the origin of the data, the returned field names, and the semantics of the notable value (device id 1 is the primary phone). An agent can call this and interpret the response without further documentation.

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?

Zero parameters, so per the rubric this is a baseline 4. The description explicitly confirms 'Takes no parameters,' which is consistent with the empty schema and removes any doubt for the agent.

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 ('List all devices linked to your Signal account') and adds the provenance detail that results come from Signal's servers rather than a local store. That scoping distinguishes it clearly from siblings like add_device, update_device, and remove_device.

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

Usage Guidelines5/5

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

Explicitly names two use cases (audit device access, obtain a device id) and routes to the tools that consume that id: update_device for rename and remove_device for unlink. Nothing is left to inference about when to reach for this tool.

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

list_groupsA
Read-onlyIdempotent

List the Signal groups this account knows, from signal-cli's local store (no network call). Call it first to get the group_id that send_group_message, send_group_attachment, update_group, leave_group, terminate_group and set_expiration_timer require, or to check your admin status. group_id (optional) returns only that group. Each group has id, name, description, member_count, members (uuid, number, is_admin, and label/label_emoji — the tag shown next to the name — when set), is_blocked, is_member and invite_link; when non-empty also pending_members (invited), requesting_members (awaiting approval), banned, permission_add_member/permission_edit_details/permission_send_message (EVERY_MEMBER or ONLY_ADMINS), message_expiration_time (seconds) and is_terminated.

ParametersJSON Schema
NameRequiredDescriptionDefault
group_idNoOptional: return only this group

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already cover readOnly, idempotent and no-network semantics, but the description reinforces the no-network behavior and, importantly, enumerates the full return shape since no output schema exists. It doesn't mention pagination or large-store performance, which keeps it short of a 5.

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

Conciseness4/5

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

Front-loaded with purpose and usage before the return-field enumeration, and every clause is dense and useful. The long field list is justified by the absence of an output schema, though it is still fairly heavy.

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

Completeness5/5

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

For a list tool with no output schema, the description fully documents the return fields (including pending/requesting/banned members and permission enums) and the local-store behavior. An agent has everything needed to call and interpret it.

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

Parameters3/5

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

Schema coverage is 100%, so the schema already documents group_id. The description restates that group_id returns only that group but adds no syntax or format detail beyond the schema; baseline 3 is appropriate.

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

Purpose5/5

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

States a specific verb and resource ('List the Signal groups this account knows') plus scope ('from signal-cli's local store'). Clearly distinguishes itself from mutation siblings like update_group and leave_group.

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

Usage Guidelines5/5

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

Explicitly says to call it first to obtain the group_id that send_group_message, update_group, leave_group, terminate_group and set_expiration_timer require, and to check admin status. This names both the purpose and the downstream dependents, leaving nothing to inference.

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

list_identitiesA
Read-onlyIdempotent

List stored Signal identity keys (safety numbers) and their trust levels, from the local store. number (optional, E.164) limits the result to one contact; omit it for all. Returns entries with number, uuid, fingerprint, safetyNumber, scannableSafetyNumber, trustLevel and addedTimestamp (epoch ms). trustLevel is TRUSTED_VERIFIED (manually verified), TRUSTED_UNVERIFIED (trusted on first use) or UNTRUSTED (key changed; sending is blocked until re-trusted). Use it when Signal reports 'safety number changed' or before trust_identity; it does not change trust itself.

ParametersJSON Schema
NameRequiredDescriptionDefault
numberNoOnly this contact's keys (E.164 phone number); omit for all

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already cover the read-only/idempotent safety profile, so the bar is lower, yet the description adds substantial context: trustLevel states TRUSTED_VERIFIED, TRUSTED_UNVERIFIED and UNTRUSTED, and notes that UNTRUSTED blocks sending until re-trusted, plus that the tool never mutates trust. That is meaningful behavioral disclosure beyond the annotations.

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

Conciseness5/5

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

Front-loads the purpose, then the filter, then the return shape, then the trust semantics and usage trigger. Sentences are dense but every one carries information an agent needs, with no filler.

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

Completeness5/5

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

With no output schema, the description compensates by enumerating all returned fields (number, uuid, fingerprint, safetyNumber, scannableSafetyNumber, trustLevel, addedTimestamp) and explaining the enum-like trust levels. Nothing needed to call or interpret it is missing.

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

Parameters3/5

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

Schema description coverage is 100% and the single parameter is fully documented there, so baseline 3 applies. The description restates E.164 format and the omit-for-all behavior without adding syntax or format detail beyond the schema.

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

Purpose5/5

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

States a specific verb and resource ('List stored Signal identity keys (safety numbers) and their trust levels, from the local store'), immediately distinguishing it from siblings like trust_identity and list_contacts. An agent knows exactly what data comes back without opening a schema.

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

Usage Guidelines5/5

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

Gives explicit triggers ('Use it when Signal reports safety number changed or before trust_identity') and an explicit exclusion of what it does not do ('it does not change trust itself'), which routes the agent to trust_identity for mutations. The 'omit it for all' filtering condition is also spelled out.

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

list_scheduled_messagesA
Read-onlyIdempotent

List messages scheduled with schedule_message, ordered by send time. include_done (boolean, default false): also include jobs that were sent, cancelled or failed; by default only pending jobs are listed. Read-only, local only. Returns an array of {id, recipient, group_id, message, send_at, created_at, status ('pending'|'sent'|'cancelled'|'failed'), error}. Use the id with cancel_scheduled_message; run_scheduled_messages sends the pending jobs that are due.

ParametersJSON Schema
NameRequiredDescriptionDefault
include_doneNoInclude already-sent, cancelled, and failed messages (default: false)

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, destructive=false, openWorld=false), so the bar is lower. The description still adds value beyond them: 'local only' scope, the full return array shape with the status enum values, and the presence of an `error` field.

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?

Four dense sentences, front-loaded with the verb and resource, then filter semantics, then return shape, then cross-tool routing. No filler and nothing redundant with the schema.

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

Completeness5/5

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

No output schema exists, yet the description supplies the return record fields and status values, plus the single parameter's semantics and relationships to the two sibling scheduling tools. An agent has everything needed to call and interpret it.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3, but the description earns above baseline by spelling out what 'done' actually means — sent, cancelled, or failed — and restating the default. That clarifies the filter semantics more than the terse schema field does.

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?

Specific verb+resource: 'List messages scheduled with schedule_message, ordered by send time.' It names the producing tool and the ordering, and clearly distinguishes itself from siblings schedule_message, cancel_scheduled_message, and run_scheduled_messages.

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

Usage Guidelines4/5

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

Explicitly scopes default behavior (pending only) vs. include_done, and routes the agent by naming the id's downstream use (cancel_scheduled_message) and the complementary sender (run_scheduled_messages). No 'when-not-to-use' clause, but the effective context is unambiguous.

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

list_sticker_packsA
Read-onlyIdempotent

List the sticker packs installed on this Signal account. No parameters. Returns signal-cli's array of packs: {packId (hex), url, installed, title, author, cover, stickers: [{id, emoji, contentType}]}. Read-only. Use packId and a sticker id with send_sticker, send_group_sticker or get_sticker. Use add_sticker_pack to install a pack from a signal.art link.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is covered; the description reinforces "Read-only" (mildly redundant) but adds genuine value by spelling out the returned pack structure, which no annotation conveys. It doesn't mention pagination or error behavior, but for a parameterless local list that gap is minor.

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?

Front-loaded with the purpose, then compactly covers the empty signature, the return shape, the safety profile, and the downstream siblings. Every sentence carries distinct information with no padding.

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

Completeness5/5

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

With no output schema and no parameters, the description compensates by documenting the exact array shape returned, including pack fields and nested sticker fields. An agent has everything needed to call it and consume the result.

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?

The tool takes zero parameters, so per the rubric the baseline is 4. The description explicitly confirms "No parameters," leaving nothing ambiguous.

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 with scope ("List the sticker packs installed on this Signal account"). It is immediately distinguishable from siblings like add_sticker_pack, get_sticker, and upload_sticker_pack without opening any schema.

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

Usage Guidelines4/5

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

It routes the agent to the relevant siblings: use packId/sticker id with send_sticker, send_group_sticker or get_sticker, and use add_sticker_pack to install. It gives clear context for the tool's role in the sticker workflow, though it never states an explicit condition for choosing this listing tool over any other alternative.

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

mark_as_unreadA
Idempotent

Mark messages as unread again in the local signal-mcp store, so get_unread returns them on its next call — e.g. to flag for follow-up. Local only: read receipts already sent and other devices are unaffected (send_read_receipt is the opposite, outward action). message_ids: list of message id strings exactly as returned by get_conversation, get_unread or search_messages; unknown ids are ignored. Idempotent. Returns {status, count} where count is the number of ids passed.

ParametersJSON Schema
NameRequiredDescriptionDefault
message_idsYesMessage id strings as returned by get_conversation, get_unread or search_messages

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already cover readOnly=false, destructive=false, idempotent=true, openWorld=false, but the description adds what those flags cannot: that the change is local-only, that already-sent read receipts and other devices are unaffected, that unknown ids are silently ignored, and the exact return shape {status, count}. The 'unknown ids are ignored' behavior is especially valuable side-effect disclosure.

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?

Front-loads the action and the store scope, then layers consequence, scope caveat, parameter semantics and return shape in short clauses. Every sentence carries distinct information; nothing repeats the schema or annotations without adding meaning.

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

Completeness5/5

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

There is no output schema, yet the description supplies the return contract ({status, count} where count is the number of ids passed), the idempotency guarantee, and the blast radius of the mutation. For a single-parameter local mutation tool, an agent has everything needed to call it correctly.

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

Parameters4/5

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

Schema coverage is 100% so the baseline is 3, but the description earns an extra point by telling the agent where valid ids come from ('exactly as returned by get_conversation, get_unread or search_messages') and what happens to ids that don't resolve. It doesn't add ordering or size-limit constraints, so it isn't a full 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?

Names a specific verb (mark as unread) plus resource (messages) and scopes it precisely to the local signal-mcp store, then states the observable consequence ('so get_unread returns them on its next call'). It also distinguishes itself from the sibling it most resembles, send_read_receipt, calling it 'the opposite, outward action'.

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 a concrete motivating scenario ('e.g. to flag for follow-up') and points at the contrasting sibling (send_read_receipt) for the outward case. It stops short of explicit when-not conditions or edge-case routing, but the context is clear enough to choose between the two.

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

pin_messageA
Idempotent

Pin a message at the top of a DM or group conversation for all participants. Pinning is visible to everyone — don't use it as a private bookmark (send_note_to_self instead). Use unpin_message to remove a pin. target_author: E.164 number of the message's sender; target_timestamp: its ms timestamp (message id in get_conversation). Give recipient (E.164) for a DM or group_id for a group; neither is an error. Contacts Signal's servers; pinning an already pinned message changes nothing. Returns {status: 'message pinned'}.

ParametersJSON Schema
NameRequiredDescriptionDefault
group_idNoGroup ID for group conversations — provide this OR recipient
recipientNoPhone number for DM conversations — provide this OR group_id
target_authorYesPhone number of the message author (E.164)
target_timestampYesTimestamp of the message to pin (from get_conversation)

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare openWorldHint, idempotentHint, and non-destructive, so the bar is lower. The description still adds real context beyond them: the pin is publicly visible to all participants, the call contacts Signal's servers, and re-pinning is a no-op (restating idempotency in plain terms). Only the return shape and any auth/rate-limit caveats are left implicit.

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

Conciseness4/5

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

Front-loaded with the core action and visibility caveat before the routing advice and parameter notes; every sentence carries information. It is dense as a single block, and the parameter guidance is interleaved with usage guidance rather than separated, which slightly hurts scannability.

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

Completeness5/5

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

For a 4-parameter mutation with no output schema, the description covers the missing return contract ('Returns {status: \'message pinned\'}'), the visibility consequence, the idempotent behavior, and both conversation-targeting modes. An agent has everything needed to call it correctly.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3, but the description adds format meaning the schema lacks: E.164 for target_author, millisecond timestamp, and the provenance of the value ('message id in get_conversation'). It also restates the recipient/group_id mutual-exclusivity in prose. It does not, however, clarify failure modes for ambiguous or mismatched identifiers.

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 (pin) and resource (message) with explicit scope: at the top of a DM or group conversation, visible to all participants. It actively distinguishes itself from two siblings by name (send_note_to_self for private bookmarks, unpin_message for removal), so an agent can route correctly without opening any schema.

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

Usage Guidelines5/5

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

Explicit when-not guidance ('don't use it as a private bookmark — send_note_to_self instead') plus the inverse operation (unpin_message) and the recipient-vs-group_id selection rule including the 'neither is an error' edge case. Nothing about tool selection is left to inference.

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

prune_storeA
DestructiveIdempotent

Delete locally stored messages older than a number of days from signal-mcp's database, together with their attachment records and search index entries. days (integer, default 180, must be positive): messages with a timestamp older than now minus this many days are deleted. Local only: nothing is deleted from Signal; irreversible locally. Returns {deleted: count, older_than_days}. Use it to keep the store small; use delete_local_messages for one conversation or clear_local_store to wipe everything.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoDelete messages older than this many days (default: 180)

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare destructiveHint=true, idempotentHint=true and openWorldHint=false, but the description adds material context beyond them: the operation is local-only, nothing is removed from Signal itself, it is irreversible locally, and it cascades into attachment records and search index entries. It also discloses the return shape {deleted, older_than_days}, which the absence of an output schema makes valuable.

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

Conciseness4/5

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

The text is a single dense paragraph that front-loads the core action before moving to parameter semantics, return value, and sibling routing. It is slightly long and the parameter sentence partially restates the schema default, but no sentence is wasted.

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

Completeness5/5

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

For a one-parameter destructive tool with no output schema, the description covers the action, its cascade effects, irreversibility, local-only scope, parameter semantics, return shape, and alternatives. An agent has everything needed to call it correctly or choose a sibling instead.

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

Parameters4/5

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

Schema coverage is 100% so the baseline is 3, but the description adds the positivity constraint ("must be positive") and the precise comparison semantics (timestamp older than now minus N days) that the schema's one-line description does not spell out. That is a modest but real increment over the structured field.

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 precise verb (delete) plus resource (locally stored messages older than N days) and explicitly scopes it to signal-mcp's database, including the cascading deletion of attachment records and search index entries. It also names the siblings it is not (delete_local_messages, clear_local_store), so an agent can distinguish it immediately.

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

Usage Guidelines5/5

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

It gives an explicit when-to-use ("keep the store small") and routes the agent to two named alternatives with their distinguishing conditions: delete_local_messages for one conversation, clear_local_store to wipe everything. Nothing is left to inference.

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

react_to_messageA
Idempotent

Add or remove your emoji reaction on a message in a DM or group. Use to acknowledge without replying; use send_message / send_group_message for a text reply. target_author: E.164 number of the message's sender; target_timestamp: its ms timestamp (message id in get_conversation, or a send_* result). emoji: e.g. '👍'. Give recipient (E.164) for a DM or group_id for a group; neither is an error. You have at most one reaction per message: a new emoji replaces the old one, repeating the same one changes nothing. remove=true retracts that reaction (emoji still required; default false). Contacts Signal's servers; not stored locally. Returns {status: 'reaction sent' | 'reaction removed'}.

ParametersJSON Schema
NameRequiredDescriptionDefault
emojiYesEmoji to react with (e.g. '👍')
removeNoRemove an existing reaction (default false)
group_idNoGroup ID for group reactions
recipientNoPhone number for DM reactions
target_authorYesPhone number of the message author
target_timestampYesTimestamp of the message to react to

TDQS

A4.8/5.0
Behavior5/5

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

Annotations cover the safety profile (readOnlyHint=false, idempotentHint=true, openWorldHint=true), and the description still adds substantive behavior: the one-reaction-per-message rule, replace-vs-no-op semantics for repeated emoji, remove=true retraction with emoji still required, and that the change hits Signal's servers rather than local storage. It even names the return payload, which no output schema provides.

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-loads the action and its purpose in the first clause, then layers targeting, semantics, and return value in a tight sequence. It is dense and semicolon-heavy, but every sentence carries distinct information rather than repetition.

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

Completeness5/5

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

For a six-parameter mutation with no output schema, the description covers sourcing the target identifiers, the mutual-exclusivity of recipient/group_id, replacement and retraction semantics, and the return shape. Nothing an agent needs to call this correctly is missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description goes further: it specifies target_author as the sender's E.164, explains that target_timestamp is a millisecond value obtainable from get_conversation or a send_* result, and clarifies the recipient/group_id pairing and the default of remove. Only minor gaps remain (no note on timestamp unit edge cases).

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

Purpose5/5

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

States a precise verb+resource ('Add or remove your emoji reaction on a message') and scopes it to DMs or groups. It explicitly contrasts itself with the sibling text-reply tools (send_message / send_group_message), so an agent can route correctly without opening a schema.

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

Usage Guidelines5/5

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

Gives an explicit when-to-use ('to acknowledge without replying') and names the alternatives for the other case. It also states the routing rule between the two targeting modes ('Give recipient for a DM or group_id for a group; neither is an error'), leaving nothing to inference.

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

receive_directA

Troubleshooting fallback: receive messages by running signal-cli receive directly, bypassing the daemon. Use only when receive_messages / get_unread fail because the daemon is stuck; it stops the daemon (holding a lock file meanwhile), runs the receive, and the daemon restarts on the next call. timeout: seconds to wait (default 5); max_messages: stop after this many (default: no limit); ignore_attachments, ignore_stories, ignore_avatars, ignore_stickers (all default false) skip downloading those. Received messages are saved to the local store and remote deletes applied; nothing is marked read. Returns a list of messages in the same shape as receive_messages; errors if signal-cli exits non-zero.

ParametersJSON Schema
NameRequiredDescriptionDefault
timeoutNoSeconds to wait for messages (default: 5)
max_messagesNoReturn after this many messages (default: no limit)
ignore_avatarsNoDon't download avatars
ignore_storiesNoDon't receive story messages
ignore_stickersNoDon't download sticker packs
ignore_attachmentsNoDon't download attachments

TDQS

A4.6/5.0
Behavior5/5

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

Adds substantial behavior beyond the annotations: it stops the daemon and holds a lock file, the daemon restarts on the next call, received messages are saved locally, remote deletes are applied, nothing is marked read, and it errors on non-zero exit. These are exactly the side effects an agent needs to know before invoking a non-read-only 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-loads the fallback framing and the daemon/lock caveat before parameters, and each clause carries information. Slightly dense, but no sentence is wasted.

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

Completeness5/5

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

With no output schema, the description covers the return shape ('same shape as receive_messages'), error behavior, and local-store side effects. An agent has everything needed to call it correctly.

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

Parameters3/5

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

Schema coverage is 100%, so the schema already documents all six parameters with defaults. The description restates timeout, max_messages and the ignore_* flags, adding only marginal framing ('skip downloading those'), so baseline 3 applies.

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

Purpose5/5

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

States a specific verb+resource ('receive messages by running signal-cli receive directly, bypassing the daemon') and immediately frames it as a troubleshooting fallback, which distinguishes it from the receive_messages / get_unread siblings.

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

Usage Guidelines5/5

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

Explicitly names when to use it ('only when receive_messages / get_unread fail because the daemon is stuck') and the alternatives it replaces, plus the condition that resolves the choice. Nothing is left to inference.

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

receive_messagesA

Poll the signal-cli daemon once for newly arrived messages and save them to the local store. Normally use get_unread instead — it polls when needed and returns unread messages in one call; use receive_direct only if the daemon is stuck. timeout: seconds to wait (integer, default 5); max_messages: stop after this many (default: no limit). Incoming edits and remote deletes are applied to stored messages instead of being returned; receipts are returned but not stored. Does not mark anything read. Returns a list of messages (id, sender, sender_name, recipient, group_id, group_name, body, timestamp, attachments, quote_id, reactions, is_read). If the background service already holds the receive lock, returns {note, messages} with up to 50 unread messages from the store instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
timeoutNoSeconds to wait for messages (default: 5)
max_messagesNoReturn after this many messages (default: no limit)

TDQS

A4.6/5.0
Behavior5/5

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

Annotations provide only generic hints (readOnlyHint=false, openWorldHint=true, idempotentHint=false, destructiveHint=false). The description adds substantial non-obvious behavior: edits and remote deletes are applied to stored messages rather than returned, receipts are returned but not stored, nothing is marked read, and a fallback shape {note, messages} is returned if the receive lock is held. This is exactly the kind of context annotations cannot convey.

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

Conciseness4/5

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

Dense and front-loaded: behavior, routing, parameters, side effects, and return shape in a compact block. Every sentence carries signal, though the return-field enumeration is a long list that slightly taxes readability.

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

Completeness5/5

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

For a non-idempotent, open-world polling tool with no output schema, the description covers side effects (what is stored vs returned, edits/deletes applied, nothing marked read), the return shape, and the lock-contention fallback. Nothing an agent needs to call it correctly is missing.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents timeout and max_messages. The description restates the defaults but adds no syntax or constraint details beyond the schema. Baseline 3 for full schema coverage.

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 ('Poll the signal-cli daemon once for newly arrived messages and save them to the local store') and explicitly differentiates from siblings get_unread and receive_direct, with a clear default preferred path.

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

Usage Guidelines5/5

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

Explicitly states when to use this vs alternatives: 'Normally use get_unread instead', and 'use receive_direct only if the daemon is stuck'. This is textbook when/when-not/alternatives guidance.

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

remove_contactA
DestructiveIdempotent

Delete a contact's entry (name, nickname, note) from your contact list; synced to your linked devices. It does not block them, delete messages or stop them messaging you — use block_contact for that. number (required, E.164). hide (default false): only hide the contact from the list and keep its data. forget (default false): delete ALL data for this recipient, including identity keys and sessions — not reversible. hide and forget are mutually exclusive (error if both). Returns status 'removed' and number. To rename instead, use update_contact.

ParametersJSON Schema
NameRequiredDescriptionDefault
hideNoHide the contact but keep its data
forgetNoDelete all data for this recipient, including identity keys and sessions
numberYesPhone number to remove (E.164 format)

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, but the description goes further: it discloses that changes sync to linked devices, that forget is irreversible and wipes identity keys and sessions, that hide/forget are mutually exclusive with an error on conflict, and that the result status is 'removed'. That is substantial behavior beyond the annotations.

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

Conciseness5/5

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

Dense but front-loaded: the core action and its scope boundaries come first, then parameter caveats and the result shape. Every sentence adds an actionable fact (alternatives, irreversibility, exclusivity, return value) without filler.

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

Completeness5/5

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

Despite having no output schema, the description states what is returned ('status removed' and number), covers the destructiveness and irreversibility of forget, and routes to sibling tools. Nothing an agent needs to call this safely is missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: it clarifies that hide keeps data versus forget deleting ALL data, and it documents the mutual-exclusivity constraint and error behavior that the schema does not express. It stops short of five only because the core per-parameter semantics largely duplicate the schema.

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

Purpose5/5

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

States a specific verb (Delete) and resource (a contact's entry) and immediately delimits scope by saying it does not block, delete messages, or stop messaging. This clearly distinguishes it from siblings block_contact and update_contact without opening their schemas.

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

Usage Guidelines5/5

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

Explicitly names when-not to use it ('use block_contact for that') and names the alternative for a related operation ('To rename instead, use update_contact'). Both exclusion and redirect are stated rather than implied.

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

remove_deviceA
DestructiveIdempotent

Permanently unlink a device from your Signal account; it immediately stops sending and receiving and can only come back by linking again with add_device. device_id (required, integer from list_devices) must be a linked device, not 1 (the primary). Only works when signal-mcp is the account's primary device — fails with 'This command doesn't work on linked devices' if signal-mcp was set up via signal-cli link. Returns status 'device removed' and device_id. To only rename a device, use update_device.

ParametersJSON Schema
NameRequiredDescriptionDefault
device_idYesDevice ID (get from list_devices)

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare destructiveHint, idempotentHint and openWorldHint, so the safety profile is covered; the description goes further by disclosing the operational consequence (device immediately stops sending and receiving), the irreversibility of the unlink, and the exact failure mode ('This command doesn't work on linked devices') when signal-mcp was set up via signal-cli link.

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

Conciseness4/5

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

Dense but front-loaded — the destructive action and its consequence come first, then constraints, then return values, then the sibling alternative. Nearly every clause carries information, though the sentence count could be trimmed slightly.

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

Completeness5/5

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

With no output schema, the description still states the return payload ('status' of 'device removed' plus device_id), covers the precondition, the failure case, and the alternative tool. Nothing needed to call it correctly is missing.

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

Parameters4/5

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

Schema coverage is 100% so the baseline is 3, but the description adds real constraint meaning beyond the schema: device_id must reference a linked device and must not be 1 (the primary). That is a validation rule an agent cannot infer from the schema alone.

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 ('Permanently unlink a device from your Signal account') and immediately distinguishes itself from the three sibling device tools (list_devices, add_device, update_device). An agent can select it without opening any schema.

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

Usage Guidelines5/5

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

Gives explicit when-to-use (permanent unlink), the alternative for the adjacent intent ('To only rename a device, use update_device'), and the recovery path (relink via add_device). It also names a hard precondition for calling it at all: signal-mcp must be the primary device.

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

remove_pinA
DestructiveIdempotent

Remove the Registration Lock PIN from your Signal account, so anyone who controls your phone number can re-register it without a PIN. No parameters. Primary device only: on a linked signal-cli setup it fails with 'This command doesn't work on linked devices'. Affects the real account immediately; undo it by calling set_pin again. Returns {status: 'PIN removed'}. Use set_pin to change the PIN instead of removing it.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already mark this as destructive, idempotent, not read-only, and open-world. The description adds valuable context beyond those hints: the exact failure on linked devices, the immediate account impact, and how to undo the operation by calling set_pin.

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

Conciseness5/5

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

The description is front-loaded, short, and every sentence carries useful information: purpose, effect, device constraint, undo path, return value, and alternative tool. No sentence is wasted.

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

Completeness5/5

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

For a zero-parameter destructive tool, the description is complete: it covers the side effect, device limitation, undo path, return value, and the relevant alternative. Annotations cover the safety profile, and no output schema exists, so the stated return value is a useful addition.

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?

The tool takes zero parameters, so the baseline is 4. The description simply restates that there are no parameters, which matches the empty schema and adds no further parameter semantics.

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

Purpose5/5

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

The description states a specific verb and resource: removing the Registration Lock PIN from a Signal account. It also immediately distinguishes the effect from set_pin by noting that set_pin should be used to change the PIN instead of removing it.

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

Usage Guidelines5/5

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

It gives explicit operational context: primary device only, linked-device failure mode, immediate real-account effect, and the alternative set_pin for changing rather than removing the PIN. This leaves little for the agent to infer.

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

run_scheduled_messagesA

Send every scheduled message whose send_at time has passed and is still pending. No parameters. Nothing else delivers scheduled messages, so call this (or run signal-mcp run-scheduled from cron) after their time; due messages are sent late, never dropped. Each due job is sent once as a real Signal message and marked 'sent' or 'failed' (failed jobs are not retried). Safe to call when nothing is due. Returns {processed: count, results: [{id, status: 'sent', timestamp} or {id, status: 'failed', error}]}. Use schedule_message to add jobs and list_scheduled_messages to inspect them.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

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

Annotations only declare readOnly=false, idempotent=false, destructive=false, openWorld=true. The description adds substantial context beyond that: due messages are sent late rather than dropped, each job is delivered once, failed jobs are not retried, it is safe to call when nothing is due, and the exact return shape. It is consistent with idempotentHint=false.

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?

Front-loads the core action in the first sentence, then layers delivery semantics, safety, return shape, and sibling routing. Every sentence carries distinct information; the dense return-value sentence is justified because there is no output schema.

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

Completeness5/5

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

With zero parameters and no output schema, the description fully compensates by documenting retry behavior, the sent/failed status values, the returned fields, and safe no-op behavior. Nothing an agent needs to call it correctly is missing.

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?

The tool takes no parameters, and the description confirms 'No parameters,' so there is nothing to disambiguate. Per the rubric, zero params yields a baseline of 4.

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 every scheduled message whose send_at time has passed and is still pending') and explicitly contrasts with the sibling tools schedule_message and list_scheduled_messages. An agent can distinguish this from the other scheduled-message tools without opening a schema.

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

Usage Guidelines5/5

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

Gives explicit when-to-invoke guidance ('call this ... after their time'), names the cron alternative, states the prerequisite condition (send_at passed and pending), and routes to schedule_message / list_scheduled_messages for the other lifecycle stages. Exclusions are covered via the 'still pending' condition.

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

schedule_messageA

Save a text message in the local store to be sent at a future time. Give exactly one target: recipient (E.164 phone number, for a direct message) or group_id (for a group). message (required): the text. send_at (required): local time as 'YYYY-MM-DDTHH:MM[:SS]' or 'YYYY-MM-DD HH:MM[:SS]' (no timezone); must be in the future. Nothing is sent at that time by itself: a due message goes out only when run_scheduled_messages (or the signal-mcp run-scheduled CLI, e.g. from cron) runs. Returns {job_id, send_at, status: 'scheduled'}. Use list_scheduled_messages to review jobs and cancel_scheduled_message to cancel one; use send_message or send_group_message to send now.

ParametersJSON Schema
NameRequiredDescriptionDefault
messageYesMessage text to send
send_atYesWhen to send — ISO datetime string (e.g. '2024-06-01T09:00:00' or '2024-06-01 09:00')
group_idNoGroup ID (for group messages). Mutually exclusive with recipient.
recipientNoPhone number in E.164 format (for DMs). Use group_id for group messages.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only record the write/non-idempotent/non-destructive profile; the description adds the critical behavior that nothing is actually sent at the scheduled time unless run_scheduled_messages (or the CLI) runs. It also discloses persistence to the local store and the exact return payload, which annotations cannot convey.

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

Conciseness4/5

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

The purpose and target rule are front-loaded, and the behavioral caveat and alternatives are grouped sensibly at the end. It is longer than strictly necessary ('message (required): the text' partly echoes the schema), but almost every sentence carries distinct, load-bearing information.

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

Completeness5/5

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

With no output schema, the description compensates by stating the return shape {job_id, send_at, status}, the send-time dependency, and the target constraint. An agent has everything needed to schedule, review, and understand the deferred-send model.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds genuine constraints beyond the schema: send_at is local time with no timezone, accepts two concrete formats, and 'must be in the future'. It also restates the mutually exclusive target rule with the E.164 requirement.

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

Purpose5/5

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

The description opens with a specific verb+resource+mechanism: 'Save a text message in the local store to be sent at a future time.' It explicitly distinguishes itself from immediate-send siblings by naming send_message and send_group_message as the 'send now' alternatives, so an agent can route correctly without opening any schema.

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

Usage Guidelines5/5

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

It names the full lifecycle siblings and the condition that selects each: list_scheduled_messages to review, cancel_scheduled_message to cancel, send_message/send_group_message for immediate sending. It also states the target-selection rule ('exactly one target: recipient or group_id'), removing ambiguity.

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

search_messagesA
Read-onlyIdempotent

Full-text search of message bodies across all conversations in the local store (SQLite FTS; no Signal server call, nothing marked read). Only messages stored on this device are found. Use get_conversation to read a chat in order. query: words to find (all words must occur; falls back to substring match if FTS fails; empty returns []). sender: only messages from this E.164 number. since (inclusive) / until (exclusive) ISO dates, e.g. since=2024-01-01, until=2024-01-02 covers all of Jan 1; invalid dates return an error. limit: max results (default 50, clamped 1-500); offset: skip N results for paging (default 0). Returns a list of messages, newest first (id, sender, sender_name, recipient, group_id, group_name, body, timestamp, attachments …).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum results to return (default 50, clamped 1-500)
queryYesKeyword or phrase to search for
sinceNoOnly messages at or after this ISO datetime (e.g. 2024-01-01 or 2024-01-01T09:00:00)
untilNoOnly messages strictly before this ISO datetime (exclusive; until=2024-01-02 includes all of Jan 1)
offsetNoSkip this many results for pagination (default 0)
senderNoFilter results to messages from this phone number (E.164)

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnly, idempotent, closed-world), but the description adds substantial behavioral context beyond them: no Signal server call, nothing marked read, only locally stored messages are found, FTS failure falls back to substring matching, and invalid dates return an error. These are non-obvious traits an agent needs.

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 purpose then capabilities then per-parameter notes in one dense paragraph; every clause carries information. It does duplicate some schema details (date examples, limit clamp), which keeps it just short of ideal.

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

Completeness5/5

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

No output schema exists, yet the description enumerates the returned fields (id, sender, sender_name, recipient, group_id, group_name, body, timestamp, attachments) and ordering (newest first), plus pagination and error behavior. An agent has everything needed to call and interpret it.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds genuine meaning: multiple words must all occur (AND semantics not in the schema's 'keyword or phrase'), empty query returns [], and boundary examples for since/until. It repeats the limit clamping and date exclusivity already in the schema.

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

Purpose5/5

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

States a specific verb (full-text search) and resource (message bodies) with a precise scope: 'across all conversations in the local store'. It explicitly distinguishes itself from get_conversation for reading a chat in order, so an agent can route without opening either schema.

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

Usage Guidelines5/5

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

Names the alternative ('Use get_conversation to read a chat in order') and defines the boundary conditions: local device only, no server call, nothing marked read. The when-to-use and when-not-to-use conditions are both explicit.

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

send_attachmentA

Send one or more files (photos, videos, documents, audio) to one Signal contact in a single message. Use send_group_attachment for groups, send_message for text only, send_sticker for stickers. Address by recipient (E.164) or username (alice.42 or username link) — exactly one. path: a single file; paths: several files sent together (one of the two is required). Files must lie inside the allowed send folders (default: the signal-mcp attachments folder, ~/Downloads, ~/Desktop, ~/Documents; override with SIGNAL_MCP_SEND_ROOTS) and not be hidden, else an error is returned. caption: text shown with the files (default empty); view_once=true lets the recipient open media only once; voice_note=true marks audio as a voice note. Reply/quote: quote_author (E.164) + quote_timestamp (ms) of the original; quote_message (quoted text; default: looked up in the local store), quote_mentions ({start, length, author}), quote_text_styles ('start:length:STYLE') and quote_attachments ('contentType[:filename[:previewFile]]') only shape the quote bubble. no_urgent=true sends without a push notification; notify_self=true delivers a normal notifying message if you are among the recipients. Contacts Signal's servers; not idempotent (repeating sends a duplicate); sends share a 20-per-minute rate limit (calls wait rather than fail). Saved to the local store (caption as body). Returns {status, timestamp}.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoSingle file path (absolute, relative, or ~/path)
pathsNoMultiple file paths to send as one message
captionNoOptional caption text shown below the attachment
usernameNoSignal username (e.g. alice.42) or username link, instead of recipient
no_urgentNoSend without the urgent flag, so the recipient gets no push notification
recipientNoPhone number in E.164 format
view_onceNoSend as view-once media — recipient can only view it once before it disappears
voice_noteNoMark audio attachments as voice notes (played inline in Signal)
notify_selfNoIf you are among the recipients, deliver as a normal (notifying) message instead of a silent sync message
quote_authorNoPhone number (E.164) of the author of the message being quoted/replied to
quote_messageNoText of the quoted message shown in the quote bubble. Default: looked up in the local store by quote_author + quote_timestamp
quote_mentionsNo@mentions inside the quoted text, same shape as mentions: {start, length, author}
quote_timestampNoTimestamp of the message being quoted/replied to (from get_conversation)
quote_attachmentsNoAttachments of the quoted message as 'contentType[:filename[:previewFile]]', e.g. 'image/png:photo.png'
quote_text_stylesNoStyles inside the quoted text as 'start:length:STYLE' (BOLD, ITALIC, SPOILER, STRIKETHROUGH, MONOSPACE)

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare a non-read-only, open-world, non-idempotent write, but the description adds substantial context beyond them: a 20-per-minute send rate limit where calls wait rather than fail, duplicate sends on repeat, errors for files outside allowed roots or hidden files, local-store persistence, and the return shape {status, timestamp}.

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 with the core action and alternatives, and its length is largely justified by 15 parameters. However, it is a dense single paragraph with semicolon-separated clauses, so structure could be improved for scanability.

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

Completeness5/5

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

Given the high parameter count, absent output schema, and rich annotations, the description is complete enough: it covers purpose, alternatives, addressing, file constraints, behavioral caveats, rate limits, persistence, and return values. No critical calling information is missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema: path and paths are mutually exclusive with one required, recipient and username are mutually exclusive, files must lie in allowed send folders, and quote fields only shape the quote bubble. The schema still carries most per-parameter detail, so this is not a full 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?

The description states a specific verb and resource: 'Send one or more files ... to one Signal contact in a single message.' It explicitly distinguishes this tool from send_group_attachment, send_message, and send_sticker, so an agent can route correctly without opening sibling schemas.

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

Usage Guidelines5/5

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

It names the alternatives and the conditions that select them: use send_group_attachment for groups, send_message for text only, send_sticker for stickers. It also states addressing rules (recipient or username, exactly one) and file-source restrictions, leaving little to inference.

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

send_contacts_syncA
Idempotent

Send your local contact list to your other linked devices as a sync message, one-way from this device outward. Takes no parameters. Use it when contacts added or renamed through signal-mcp do not appear on your phone or desktop. Contacts no one else and changes nothing locally. Returns status 'contacts synced to linked devices'. To pull data from the primary device instead, use send_sync_request.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

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

Annotations declare readOnlyHint=false but destructiveHint=false, which is ambiguous on its own; the description resolves this by clarifying it 'changes nothing locally' and 'contacts no one else,' and adds the one-way direction and the literal return value. That is real context beyond the structured hints.

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?

Front-loads what the tool does, then trigger, then side-effect profile, then return value, then alternative. Every sentence carries distinct information with no filler.

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

Completeness5/5

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

There is no output schema, but the description states the exact return status ('contacts synced to linked devices'), covers side effects, directionality, and the alternative tool. Nothing needed to invoke it correctly is missing.

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?

Zero parameters, so the baseline is 4. The description reinforces this with 'Takes no parameters,' which is helpful but adds nothing the empty schema does not already imply.

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 contact list as a sync message) plus the direction of flow, 'one-way from this device outward.' It explicitly contrasts with the sibling send_sync_request, so an agent can distinguish it without opening schemas.

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

Usage Guidelines5/5

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

Gives a concrete trigger condition ('when contacts added or renamed through signal-mcp do not appear on your phone or desktop') and names the alternative ('to pull data from the primary device instead, use send_sync_request'). This is explicit when-to-use plus alternative routing.

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

send_group_attachmentA

Send one or more files (photos, videos, documents, audio) to a Signal group in a single message. Use send_attachment for a single contact, send_group_message for text only. group_id comes from list_groups. path: a single file; paths: several files sent together (one of the two is required). Files must lie inside the allowed send folders (default: the signal-mcp attachments folder, ~/Downloads, ~/Desktop, ~/Documents; override with SIGNAL_MCP_SEND_ROOTS) and not be hidden, else an error is returned. caption: text shown with the files (default empty); view_once=true lets each member open media only once; voice_note=true marks audio as a voice note. Reply/quote: quote_author (E.164) + quote_timestamp (ms) of the original; quote_message (quoted text; default: looked up in the local store), quote_mentions ({start, length, author}), quote_text_styles ('start:length:STYLE') and quote_attachments ('contentType[:filename[:previewFile]]') only shape the quote bubble. no_urgent=true sends without a push notification; notify_self=true delivers a normal notifying message if you are among the recipients. Contacts Signal's servers; not idempotent (repeating sends a duplicate); sends share a 20-per-minute rate limit (calls wait rather than fail). Saved to the local store (caption as body). Returns {status, timestamp}.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoSingle file path (absolute, relative, or ~/path)
pathsNoMultiple file paths to send as one message
captionNoOptional caption text shown below the attachment
group_idYesGroup ID (get from list_groups)
no_urgentNoSend without the urgent flag, so the recipient gets no push notification
view_onceNoSend as view-once media — each recipient can only view it once
voice_noteNoMark audio attachments as voice notes (played inline in Signal)
notify_selfNoIf you are among the recipients, deliver as a normal (notifying) message instead of a silent sync message
quote_authorNoPhone number (E.164) of the author of the message being quoted/replied to
quote_messageNoText of the quoted message shown in the quote bubble. Default: looked up in the local store by quote_author + quote_timestamp
quote_mentionsNo@mentions inside the quoted text, same shape as mentions: {start, length, author}
quote_timestampNoTimestamp of the message being quoted/replied to (from get_conversation)
quote_attachmentsNoAttachments of the quoted message as 'contentType[:filename[:previewFile]]', e.g. 'image/png:photo.png'
quote_text_stylesNoStyles inside the quoted text as 'start:length:STYLE' (BOLD, ITALIC, SPOILER, STRIKETHROUGH, MONOSPACE)

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare the safety profile (readOnly=false, idempotent=false, openWorld=true), so the bar is lower, yet the description adds substantial context: sendable-folder restriction with default roots and env override, error on hidden files, contact with Signal servers, non-idempotency (duplicate sends), a 20/min shared rate limit that waits rather than fails, and store persistence.

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 purpose and sibling routing, then groups related concerns (files, caption/media flags, quoting, notification, side effects). It is dense and long, but with 14 parameters each clause carries information, so little is wasted.

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

Completeness5/5

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

For a 14-parameter, non-idempotent mutation tool with no output schema, the description covers everything an agent needs: file constraints, flag semantics, quorum/quote behavior, side effects (server contact, rate limit, local store), and the return shape {status, timestamp}.

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 100%, so baseline is 3. The description goes beyond the schema by stating that path/paths are mutually exclusive with one required, and that quote_attachments/quote_text_styles/quotes only shape the quote bubble, but most parameter meaning is already documented in the schema.

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

Purpose5/5

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

States a specific verb+resource+scope: 'Send one or more files ... to a Signal group in a single message.' It also explicitly distinguishes itself from send_attachment (single contact) and send_group_message (text only), so an agent can route without opening other schemas.

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

Usage Guidelines5/5

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

Names the alternatives and the condition that selects each ('Use send_attachment for a single contact, send_group_message for text only') and points to list_groups for group_id. The file-root constraint further defines when a call will succeed vs. error.

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

send_group_messageA

Send a text message to a Signal group (end-to-end encrypted to all members). Use send_message for a single contact, send_group_attachment for files. group_id comes from list_groups. message is the text. @mentions: put the name in the text and pass mentions [{start, length, author (E.164)}]; start/length are UTF-16 code units, not codepoints — an emoji before the mention shifts the offset by 2, not 1. formatting=true turns bold, italic, strikethrough, monospace and ||spoiler|| into real Signal formatting (markers are removed from the sent text); with it, mention offsets refer to the text as you wrote it, markers included, and are adjusted for you. Leave it off for text with literal asterisks or backticks. Reply/quote: quote_author (E.164) + quote_timestamp (ms) of the original; quote_message (quoted text; default: looked up in the local store), quote_mentions ({start, length, author}), quote_text_styles ('start:length:STYLE') and quote_attachments ('contentType[:filename[:previewFile]]') only shape the quote bubble. Link preview card: preview_url (must also appear in the text), preview_title (needed for the card to render), preview_description, preview_image (local file). Story reply: story_author (E.164, required with story_timestamp) + story_timestamp (ms). no_urgent=true sends without a push notification; notify_self=true delivers a normal notifying message if you are among the recipients. Contacts Signal's servers; not idempotent (repeating sends a duplicate); sends share a 20-per-minute rate limit (calls wait rather than fail). The sent message is saved to the local store. Returns {status, timestamp, group_id}; timestamp is the target_timestamp for edit_message, react_to_message or delete_group_message.

ParametersJSON Schema
NameRequiredDescriptionDefault
messageYesMessage text to send
group_idYesGroup ID (from list_groups)
mentionsNoList of @mentions. Each item: {start: offset of the mention in the message (UTF-16 code units, not codepoints), length: mention length (UTF-16 code units), author: E.164 phone number of the mentioned member}. Example: message='Hello @Alice', mentions=[{start:6,length:6,author:'+1234567890'}]
no_urgentNoSend without the urgent flag, so the recipient gets no push notification
formattingNoConvert **bold**, *italic*, ~~strikethrough~~, `monospace`, ||spoiler|| to Signal text formatting. Default false.
notify_selfNoIf you are among the recipients, deliver as a normal (notifying) message instead of a silent sync message
preview_urlNoURL for a link preview card; the same URL must also appear in the message text
quote_authorNoPhone number (E.164) of the author of the message being quoted/replied to
story_authorNoPhone number of the story's author, to reply to a story
preview_imageNoLocal image file for the link preview thumbnail
preview_titleNoLink preview title (needed for the card to render)
quote_messageNoText of the quoted message shown in the quote bubble. Default: looked up in the local store by quote_author + quote_timestamp
quote_mentionsNo@mentions inside the quoted text, same shape as mentions: {start, length, author}
quote_timestampNoTimestamp of the message being quoted/replied to (from get_conversation)
story_timestampNoTimestamp of the story being replied to
quote_attachmentsNoAttachments of the quoted message as 'contentType[:filename[:previewFile]]', e.g. 'image/png:photo.png'
quote_text_stylesNoStyles inside the quoted text as 'start:length:STYLE' (BOLD, ITALIC, SPOILER, STRIKETHROUGH, MONOSPACE)
preview_descriptionNoLink preview description

TDQS

A4.9/5.0
Behavior5/5

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

Goes well beyond the annotations: discloses end-to-end encryption, that it contacts Signal's servers, that it is not idempotent (repeating sends a duplicate), a concrete 20-per-minute shared rate limit that makes calls wait rather than fail, local-store persistence, and the exact return shape {status, timestamp, group_id} with how timestamp feeds edit/react/delete. This is precisely the kind of destructive/write behavior context the annotations alone (idempotentHint=false, openWorldHint=true) cannot convey.

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

Conciseness4/5

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

Front-loads purpose and alternatives, then handles the complex optional behaviors; nearly every sentence carries information. It is, however, a single dense block for 18 parameters and would scan better as grouped bullets, and a few clauses (e.g., restating message/group_id) are slightly redundant with the schema.

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

Completeness5/5

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

For a write tool with no output schema, the description supplies the return shape, side effects (persistence, duplicate-on-retry, rate limiting), and the full set of interaction paths (mentions, formatting, reply/quote, story reply, previews). Nothing needed to call it correctly appears to be missing.

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?

With 100% schema coverage the baseline is 3, but the description adds real meaning: it explains that mention start/length are UTF-16 code units (with the concrete emoji-shifts-by-2 example) and that enabling formatting changes how offsets are interpreted and are auto-adjusted. It also clarifies that quote_* fields only shape the quote bubble and that preview_url must appear in the text, resolving non-obvious interactions the schema cannot express.

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 with scope: 'Send a text message to a Signal group (end-to-end encrypted to all members)'. It immediately differentiates from siblings by naming send_message for single contacts and send_group_attachment for files, so an agent can route correctly without opening any schema.

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

Usage Guidelines5/5

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

Explicitly names alternatives and the conditions that select them (send_message for a contact, send_group_attachment for files). It also grounds required inputs (group_id from list_groups) and distinguishes the reply/quote path from the story-reply path, leaving little to inference.

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

send_group_stickerA

Send one sticker from an installed sticker pack to a Signal group; it renders as a sticker, not a file. Use send_sticker for a single contact, send_group_attachment for ordinary images. group_id: from list_groups. pack_id: hex pack id and sticker_id: integer index within the pack, both from list_sticker_packs; an uninstalled pack or invalid id returns an error — install packs first with add_sticker_pack (signal.art URL). Contacts Signal's servers; not idempotent (repeating sends a duplicate); sends share a 20-per-minute rate limit (calls wait rather than fail). Saved locally as '[sticker pack:id]'. Returns {status, timestamp}.

ParametersJSON Schema
NameRequiredDescriptionDefault
pack_idYesSticker pack ID (hex string from list_sticker_packs)
group_idYesGroup ID (get from list_groups)
sticker_idYesSticker ID within the pack (from list_sticker_packs)

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare non-readOnly, openWorld, non-idempotent and non-destructive, but the description adds operational detail they don't carry: duplicate sends on repeat, a 20-per-minute shared rate limit where calls wait rather than fail, server contact, and local persistence as '[sticker pack:id]'. This is genuinely additive context beyond the structured hints.

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

Conciseness4/5

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

Dense but well front-loaded — the core action and the not-a-file behavior lead, followed by routing, parameter sourcing, side effects, and return shape. Slightly long, but nearly every clause carries distinct information.

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

Completeness5/5

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

With no output schema, the description still gives the return shape {status, timestamp}, plus error conditions, rate-limit behavior, and persistence. For a 3-param mutating tool, an agent has everything needed to call it correctly and predict the outcome.

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

Parameters4/5

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

Schema coverage is 100% and each param is self-documented, so baseline is 3. The description still adds value: it specifies pack_id is hex, sticker_id is an integer index within the pack, group_id comes from list_groups, and notes that an uninstalled pack or invalid id returns an error rather than silently failing.

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 one sticker from an installed sticker pack to a Signal group') and explicitly disambiguates the outcome ('renders as a sticker, not a file'). It names the closest siblings (send_sticker, send_group_attachment) so an agent can route without opening schemas.

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

Usage Guidelines5/5

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

Explicitly routes to send_sticker for single contacts and send_group_attachment for ordinary images, and adds the prerequisite path: install packs first with add_sticker_pack. Both when-to-use and the alternative-selection conditions are stated.

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 text message to one Signal contact (end-to-end encrypted). Use send_group_message for groups, send_attachment for files, send_note_to_self for your own Note to Self, schedule_message to send later. Address the contact by recipient (E.164, e.g. +4915112345678) or username (alice.42 or a username link) — exactly one, otherwise an error. message is the text; formatting=true turns bold, italic, strikethrough, monospace and ||spoiler|| into real Signal formatting (markers removed; leave off for literal asterisks/backticks). Reply/quote: quote_author (E.164) + quote_timestamp (ms) of the original; quote_message (quoted text; default: looked up in the local store), quote_mentions ({start, length, author}), quote_text_styles ('start:length:STYLE') and quote_attachments ('contentType[:filename[:previewFile]]') only shape the quote bubble. Link preview card: preview_url (must also appear in the text), preview_title (needed for the card to render), preview_description, preview_image (local file). Story reply: story_author (E.164, required with story_timestamp) + story_timestamp (ms). no_urgent=true sends without a push notification; notify_self=true delivers a normal notifying message if you are among the recipients. end_session=true instead resets the encrypted session (message ignored; troubleshooting only). Contacts Signal's servers; not idempotent (repeating sends a duplicate); sends share a 20-per-minute rate limit (calls wait rather than fail). The sent message is saved to the local store. Returns {status, timestamp, recipient}; timestamp is the target_timestamp for edit_message, react_to_message or delete_message.

ParametersJSON Schema
NameRequiredDescriptionDefault
messageYesMessage text to send
usernameNoSignal username (e.g. alice.42) or username link, instead of recipient
no_urgentNoSend without the urgent flag, so the recipient gets no push notification
recipientNoPhone number in E.164 format (e.g. +1234567890)
formattingNoConvert **bold**, *italic*, ~~strikethrough~~, `monospace`, ||spoiler|| to Signal text formatting. Default false.
end_sessionNoReset the session with this contact instead of sending a message
notify_selfNoIf you are among the recipients, deliver as a normal (notifying) message instead of a silent sync message
preview_urlNoURL for a link preview card; the same URL must also appear in the message text
quote_authorNoPhone number (E.164) of the author of the message being quoted/replied to
story_authorNoPhone number of the story's author, to reply to a story
preview_imageNoLocal image file for the link preview thumbnail
preview_titleNoLink preview title (needed for the card to render)
quote_messageNoText of the quoted message shown in the quote bubble. Default: looked up in the local store by quote_author + quote_timestamp
quote_mentionsNo@mentions inside the quoted text, same shape as mentions: {start, length, author}
quote_timestampNoTimestamp of the message being quoted/replied to (from get_conversation)
story_timestampNoTimestamp of the story being replied to
quote_attachmentsNoAttachments of the quoted message as 'contentType[:filename[:previewFile]]', e.g. 'image/png:photo.png'
quote_text_stylesNoStyles inside the quoted text as 'start:length:STYLE' (BOLD, ITALIC, SPOILER, STRIKETHROUGH, MONOSPACE)
preview_descriptionNoLink preview description

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare readOnly=false, openWorld=true, idempotent=false, destructive=false. The description goes further with operationally critical context the annotations cannot convey: a 20-per-minute shared rate limit where calls wait rather than fail, non-idempotent duplicates, local-store persistence, and the {status, timestamp, recipient} return (valuable since no output schema exists).

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?

Roughly 280 words for a 19-parameter tool, front-loaded with purpose and sibling routing before the parameter detail. Dense and mostly earn-its-place, though the mid-section reads as a run-on catalog of quote/preview fields that could be tightened with structure.

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

Completeness5/5

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

Given 19 parameters, no output schema, and an outward-facing side-effecting call, the description covers safety-adjacent behavior (rate limits, duplicates, session reset, server contact), the return shape, and every non-obvious parameter interaction. Nothing an agent needs to call it correctly is missing.

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 already 100%, but the description adds cross-parameter semantics the schema omits: recipient/username mutual exclusivity with an error condition, quote_author+quote_timestamp pairing, story_author+story_timestamp mutual requirement, and 'preview_url must also appear in the text' / 'preview_title needed for the card to render'. This is genuine net-new meaning, not restatement.

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+resource+destination ('Send a text message to one Signal contact') and immediately distinguishes itself from send_group_message, send_attachment, send_note_to_self, and schedule_message. An agent can route to the right sibling without opening any schema.

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

Usage Guidelines5/5

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

Explicit alternative routing is given for groups, files, Note to Self, and scheduled sends, plus the constraining condition 'exactly one, otherwise an error' for recipient/username. This is textbook when-to-use/when-not guidance.

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

send_message_request_responseA
Idempotent

Accept or decline a message request from someone not in your contacts. sender (required, E.164) is who sent the request; accept (required): true accepts, which shares your profile with them; false declines (deletes the request) and turns profile sharing off. Declining does not block them — use block_contact for that. The decision is recorded locally and synced to your linked devices; the sender is not sent a message. Returns status 'message request accepted' or 'message request declined' and sender.

ParametersJSON Schema
NameRequiredDescriptionDefault
acceptYestrue to accept (shares your profile), false to decline (does not block)
senderYesPhone number (E.164) of the contact who sent the message request

TDQS

A4.7/5.0
Behavior5/5

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

Goes well beyond the annotations: accept shares your profile, decline deletes the request and turns profile sharing off, the decision is recorded locally and synced to linked devices, and no message is sent to the sender. This is unusually rich behavioral context for a mutating tool.

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

Conciseness5/5

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

Front-loaded with the core action, then consequences, then the sibling disambiguation, then return values. Dense but every clause earns its place with no redundancy.

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

Completeness5/5

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

With no output schema, the description supplies the return values ('message request accepted'/'declined' plus sender). Side effects, device sync, and the non-blocking distinction are all covered, so nothing needed to call it correctly is missing.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents both parameters (E.164 sender, accept semantics). The description restates this but adds little syntax or format detail beyond the schema, so the baseline 3 applies.

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

Purpose5/5

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

States the specific verbs (accept/decline) and the exact resource (a message request from someone not in your contacts), which is distinct from every sibling. An agent can identify the operation without opening the schema.

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

Usage Guidelines5/5

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

Explicitly routes the agent: declining 'does not block them — use block_contact for that,' naming the alternative and the condition that selects it. Both accept and decline outcomes are spelled out, leaving nothing to inference.

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

send_note_to_selfA

Send a message to your own Note to Self chat; it syncs to all your linked Signal devices. Use for reminders, bookmarks or drafts; use send_message to message anyone else. message always supports bold, italic, strikethrough, monospace, ||spoiler|| (markers become Signal formatting) — e.g. a bold title per note. attachments: list of local file paths (e.g. a QR code); voice_note=true marks audio as a voice note. To thread a follow-up under an earlier note pass quote_author (your own number) + quote_timestamp (from a prior send_note_to_self result); quote_message, quote_mentions, quote_text_styles, quote_attachments optionally shape the quote bubble. Link preview card: preview_url (must also appear in the text), preview_title (needed for the card to render), preview_description, preview_image (local file). no_urgent=true sends without a push notification; notify_self=true delivers a normal notifying message if you are among the recipients. Combine content in one call rather than several. Not idempotent; shares the 20-sends-per-minute rate limit. Saved to the local store. Returns {status, timestamp}.

ParametersJSON Schema
NameRequiredDescriptionDefault
messageYesNote text to save. Supports **bold**, *italic*, ~~strikethrough~~, `monospace`, ||spoiler||
no_urgentNoSend without the urgent flag, so the recipient gets no push notification
voice_noteNoMark audio attachments as voice notes (played inline in Signal)
attachmentsNoFile paths to attach (e.g. a QR code or screenshot)
notify_selfNoIf you are among the recipients, deliver as a normal (notifying) message instead of a silent sync message
preview_urlNoURL for a link preview card; the same URL must also appear in the message text
quote_authorNoYour own account number, to thread this note under a previous one
preview_imageNoLocal image file for the link preview thumbnail
preview_titleNoLink preview title (needed for the card to render)
quote_timestampNoTimestamp of the note being followed up on (from a prior send_note_to_self result)
preview_descriptionNoLink preview description

TDQS

A4.4/5.0
Behavior4/5

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

Annotations cover the safety profile (readOnly=false, destructive=false, openWorld=true, idempotent=false), and the description adds real context beyond them: the 20-sends-per-minute rate limit, local-store persistence, syncing across linked devices, and the {status, timestamp} return shape. 'Not idempotent' merely restates the annotation, but the rate-limit and persistence details are genuine additions.

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

Conciseness4/5

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

Purpose and the key routing decision are front-loaded, and the dense sentences each carry distinct information (formatting, attachments, quoting, previews, notifications, rate limit). It is long for one description, but little is wasted.

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

Completeness5/5

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

For an 11-parameter mutation tool, the definition covers routing, formatting, side effects (rate limit, local persistence), the return value, and quoting/link-preview mechanics. Nothing essential to a correct call is missing despite the absence of an output schema.

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

Parameters3/5

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

Schema coverage is 100%, so the schema already documents all 11 parameters, and most of the description's per-parameter prose (preview_url must appear in text, preview_title needed to render, quote_author being your own number) duplicates it. It adds only marginal meaning, e.g. how quote_author plus quote_timestamp combine to thread a follow-up.

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

Purpose5/5

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

States a precise verb and resource ('Send a message to your own Note to Self chat') and immediately distinguishes it from the sibling send_message. An agent can select it against send_message/send_group_message without opening a schema.

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

Usage Guidelines5/5

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

Explicitly names the intended uses (reminders, bookmarks, drafts) and the alternative ('use send_message to message anyone else'). Guidance about combining content in one call also shapes invocation, so both when and how are covered.

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

send_read_receiptA
Idempotent

Send a read receipt to a contact so their Signal app shows your messages as 'Read', and mark those messages read in the local store. Use after reading a DM with get_conversation (which marks read locally but sends no receipt). Not for groups. sender: E.164 number of the contact who sent the messages. timestamps: list of their messages' ms timestamps (the message id in get_conversation), batched in one call. Only shown if the sender has read receipts enabled. Contacts Signal's servers; repeating is harmless. Returns {status: 'read receipt sent'}.

ParametersJSON Schema
NameRequiredDescriptionDefault
senderYesPhone number (E.164) of the contact whose messages you are acknowledging
timestampsYesMillisecond timestamps of the messages to acknowledge (the message id in get_conversation)

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnly=false, openWorld=true, idempotent=true, destructive=false, and the description's 'Contacts Signal's servers; repeating is harmless' partly restates those. However it adds genuinely new behavior: it marks messages read in the local store, it is 'Only shown if the sender has read receipts enabled', and it returns {status: 'read receipt sent'}. These side-effect and conditional details go beyond the structured fields.

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

Conciseness4/5

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

Front-loaded with purpose, then usage, params, caveats, and return value in a logical order. Slightly long, and the server/idempotency sentence partially overlaps the annotations, but every sentence carries usable information.

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

Completeness5/5

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

No output schema exists, yet the description supplies the return shape, the side effects, the recipient-side visibility condition, and full usage routing. An agent has everything needed to invoke it correctly.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3. The description adds real meaning beyond the schema: it clarifies that timestamps are the contact's message timestamps and should be 'batched in one call', and maps them to 'the message id in get_conversation', which the schema does not explain.

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 read receipt to a contact') and immediately scopes it ('Not for groups'), distinguishing it from the many send_* siblings. It also names the related tool get_conversation, so the agent can place it precisely.

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

Usage Guidelines5/5

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

Gives explicit when-to-use ('Use after reading a DM with get_conversation') including the reasoning (get_conversation marks read locally but sends no receipt), an explicit when-not ('Not for groups'), and the alternative context. Nothing is left to inference.

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

send_stickerA

Send one sticker from an installed sticker pack to a single contact; it renders as a sticker, not a file. Use send_group_sticker for groups, send_attachment for ordinary images. recipient: E.164 number. pack_id: hex pack id and sticker_id: integer index within the pack, both from list_sticker_packs; an uninstalled pack or invalid id returns an error — install packs first with add_sticker_pack (signal.art URL). Contacts Signal's servers; not idempotent (repeating sends a duplicate); sends share a 20-per-minute rate limit (calls wait rather than fail). Saved locally as '[sticker pack:id]'. Returns {status, timestamp}.

ParametersJSON Schema
NameRequiredDescriptionDefault
pack_idYesSticker pack ID (hex string from list_sticker_packs)
recipientYesPhone number in E.164 format
sticker_idYesSticker ID within the pack (from list_sticker_packs)

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=false, idempotentHint=false, openWorldHint=true, so the safety profile is covered; the description goes well beyond by disclosing the 20-per-minute shared rate limit and that calls wait rather than fail, that sends contact Signal's servers, how the sticker is saved locally, and the error behavior on invalid pack/id. The non-idempotency restatement adds the concrete consequence (repeating sends a duplicate).

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

Conciseness4/5

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

Purpose and sibling routing are front-loaded in the first two clauses, and nearly every clause carries operational information. It is dense with semicolons and repeats parameter facts already at 100% schema coverage, so it is efficient rather than maximally tight.

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

Completeness5/5

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

With no output schema, the description supplies the return shape ({status, timestamp}) and covers prerequisites, rate limiting, error cases, and side effects. Nothing an agent needs to call this correctly is missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: recipient must be E.164, pack_id is a hex id and sticker_id an integer index within the pack, both sourced from list_sticker_packs, plus the error semantics for invalid or uninstalled packs. It restates some schema content verbatim, which caps this below 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 (send), resource (sticker from an installed pack), and scope (one sticker, single contact), plus a clarifying contrast that it renders as a sticker rather than a file. It explicitly names the sibling tools it is not (send_group_sticker, send_attachment), so an agent can route without opening schemas.

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

Usage Guidelines5/5

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

Explicitly states when to use alternatives: send_group_sticker for groups, send_attachment for ordinary images. It also gives a prerequisite chain (install packs first with add_sticker_pack via signal.art URL) and the failure condition (uninstalled pack or invalid id returns an error).

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

send_storyA

Post an image or video as a Signal story, visible to its audience for 24 hours. Use send_message / send_attachment to message someone directly. path: one local image or video file; Files must lie inside the allowed send folders (default: the signal-mcp attachments folder, ~/Downloads, ~/Desktop, ~/Documents; override with SIGNAL_MCP_SEND_ROOTS) and not be hidden, else an error is returned. group_id (from list_groups) posts to that group's story instead of My Story. allow_replies (default true): false disables replies. Contacts Signal's servers; not idempotent (each call posts a new story); shares the 20-sends-per-minute rate limit; not saved to the local store. Returns {status: 'posted', timestamp}.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesImage or video file to post
group_idNoPost to this group's story instead of My Story (from list_groups)
allow_repliesNoAllow viewers to reply (default: true)

TDQS

A4.8/5.0
Behavior5/5

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

Annotations cover openWorld and non-idempotency, but the description adds substantially more: the 20-sends-per-minute rate limit, that the story is not saved to the local store, that files must lie within allowed send roots and not be hidden, and the exact return shape. These are behavioral traits beyond the structured fields.

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

Conciseness4/5

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

Purpose, alternatives and the path constraint are front-loaded, and the sentence flow mirrors call order. It is dense and slightly packed, but each clause (rate limit, local-store, non-idempotency, return value) earns its place.

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

Completeness5/5

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

No output schema exists, yet the description supplies the return value ({status: 'posted', timestamp}), the visibility window, failure conditions (hidden file / outside roots) and rate-limit context. Nothing an agent needs to invoke it correctly is missing.

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

Parameters4/5

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

Schema coverage is 100% (baseline 3), and the description still adds meaning beyond it: path is constrained to one local image/video inside allowed folders (with the env override), group_id must come from list_groups, and allow_replies=false disables replies. Adds real value over the terse schema descriptions.

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+resource ('Post an image or video as a Signal story') with scope (24-hour visibility) and immediately names the sibling tools it is not (send_message / send_attachment) for direct messaging. An agent can route between these without opening a schema.

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

Usage Guidelines5/5

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

Explicitly names alternatives ('Use send_message / send_attachment to message someone directly') and the condition selecting the group variant ('group_id (from list_groups) posts to that group's story instead of My Story'). When-to-use and when-not logic is fully specified.

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

send_sync_requestA
Idempotent

Ask your primary Signal device to send this linked device its contacts, groups and settings. Takes no parameters. Use it when list_contacts or list_groups is missing entries that exist on your phone; it is meant for linked setups. Asynchronous: the call returns status 'sync requested' at once and the data arrives over the next seconds through the normal receive loop. It does not fetch new messages — use receive_messages for that. To push your contacts the other way, use send_contacts_sync.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

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

Annotations cover the safety profile (readOnlyHint=false, idempotentHint=true, destructiveHint=false), and the description adds real behavior beyond them: the call is asynchronous, returns status 'sync requested' immediately, and the data arrives through the normal receive loop. It stops short of describing failure modes or what happens if the primary device is offline.

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?

Front-loads the action, then delivery semantics, then routing alternatives. Every sentence carries distinct information; there is no repetition of the schema or annotations.

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

Completeness5/5

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

No output schema exists, yet the description discloses the immediate return status and the later asynchronous arrival path, so an agent knows both what it gets back and what happens next. Complete for a zero-parameter trigger tool.

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

Parameters4/5

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

Zero parameters, which sets the baseline at 4 per the rubric. The description confirms 'Takes no parameters,' so nothing is left ambiguous.

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 ('Ask your primary Signal device to send this linked device its contacts, groups and settings') and explicitly separates itself from siblings like receive_messages and send_contacts_sync. An agent can identify the tool without opening the schema.

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

Usage Guidelines5/5

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

Gives an explicit trigger ('when list_contacts or list_groups is missing entries that exist on your phone'), a scope constraint ('meant for linked setups'), an exclusion ('does not fetch new messages — use receive_messages'), and the reverse-direction alternative ('send_contacts_sync').

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

set_expiration_timerA
Idempotent

Set or turn off the disappearing-messages timer of a one-to-one or group chat. expiration_seconds (required): lifetime of new messages in seconds, 0 disables; common values 3600 (1h), 86400 (1d), 604800 (1w), 2592000 (30d). Pass recipient (E.164) for a direct chat or group_id (from list_groups) for a group; one is required, and group_id wins if both are given. Every participant is notified and the timer applies to new messages; already sent messages are unaffected. For a group this is the same as update_group with expiration_seconds. Returns status and seconds.

ParametersJSON Schema
NameRequiredDescriptionDefault
group_idNoGroup ID (from list_groups) for a group conversation; wins if recipient is also given
recipientNoPhone number (E.164) for a direct conversation
expiration_secondsYesTimer in seconds (0 to disable). Common: 3600=1h, 86400=1d, 604800=1w

TDQS

A4.6/5.0
Behavior5/5

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

Goes well beyond the annotations (which only cover the safety/idempotency profile): it discloses that every participant is notified, that the timer applies only to new messages while already-sent messages are unaffected, and that the response contains status and seconds. These are non-obvious side effects an agent needs.

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

Conciseness4/5

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

A single dense paragraph that front-loads the action, then constraints, then side effects. Every clause carries information; slightly packed but not padded.

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

Completeness5/5

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

No output schema exists, and the description compensates by stating the return ('status and seconds'). Addressing, disabling semantics, side effects, and the sibling equivalence are all covered, leaving nothing essential for correct invocation.

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

Parameters4/5

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

With 100% schema coverage the baseline is 3, but the description adds real value: the semantics of 0 (disable), a unit hint, a common-value table including 30d (2592000) which is absent from the schema, and the group_id-over-recipient precedence. It stops short of 5 only because most of this is a restatement plus modest additions.

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: setting/disabling the disappearing-messages timer for a 1:1 or group chat. It distinguishes itself from neighbors by naming update_group as the equivalent path for groups, so an agent can route without opening another schema.

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 selection rules for its two addressing modes (recipient vs group_id, with group_id winning) and explicitly tells the agent that update_group with expiration_seconds is the equivalent operation. It lacks an explicit 'do not use when...' exclusion, which keeps it short of a 5.

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

set_pinA
Idempotent

Set or replace the Registration Lock PIN on your Signal account, so re-registering your phone number elsewhere (e.g. after a SIM swap) requires this PIN. pin (string, required): the new PIN, numeric, e.g. '123456'. Primary device only: on a linked signal-cli setup it fails with 'This command doesn't work on linked devices'. Affects the real account immediately; calling again with a new pin replaces the old one. If you forget it, re-registration is blocked until the lock lapses after 7 days of inactivity. Returns {status: 'PIN set'}. Use remove_pin to turn the lock off; finish_change_number needs this PIN when changing numbers.

ParametersJSON Schema
NameRequiredDescriptionDefault
pinYes4–20 digit numeric PIN (e.g. '123456')

TDQS

A4.6/5.0
Behavior5/5

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

Goes well beyond the annotations: states the effect is immediate on the real account, that re-calling replaces the old PIN, that it fails on linked devices, and the serious consequence of forgetting it (re-registration blocked until the lock lapses after 7 days). It also discloses the return payload {status: 'PIN set'}. This is exactly the additional context annotations cannot carry.

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

Conciseness4/5

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

Front-loaded with purpose, then constraints, consequences, return value, and sibling routing — each sentence earns its place. Slightly long and the PIN-format clause duplicates the schema, but no filler or padding.

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

Completeness5/5

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

For a single-parameter mutation with no output schema, the description covers device requirements, idempotent replacement behavior, irreversibility/forgetting consequences, the return shape, and related tools. Nothing an agent needs to call it safely is missing.

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

Parameters3/5

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

Schema coverage is 100% and the schema already documents the parameter as '4–20 digit numeric PIN (e.g. 123456)'. The description's 'numeric, e.g. 123456' adds nothing new and actually omits the 4–20 length range the schema provides. Baseline 3 for a fully-covered single parameter.

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+resource ('Set or replace the Registration Lock PIN on your Signal account') and disambiguates from the similarly named pin_message/unpin_message siblings by specifying the account-level Registration Lock. An agent can distinguish it from remove_pin and pin_message without opening any schema.

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

Usage Guidelines5/5

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

Explicitly routes to alternatives: 'Use remove_pin to turn the lock off' and notes finish_change_number requires this PIN when changing numbers. It also gives a hard usage constraint ('Primary device only: on a linked signal-cli setup it fails'), which is exactly the when/when-not guidance an agent needs.

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

set_typingA
Idempotent

Show or cancel the 'typing…' indicator in a DM or group. Purely cosmetic; use before send_message / send_group_message in an automated reply. recipient: E.164 number for a DM; group_id for a group (from list_groups); at least one is required. stop=true cancels an active indicator early (default false = start). The indicator expires by itself after ~15 seconds and is cleared when you send, so stop is rarely needed; one call per message is enough — don't loop. If the recipient disabled typing indicators it is silently ignored. Contacts Signal's servers; nothing is stored. Returns {status: 'typing indicator sent'}.

ParametersJSON Schema
NameRequiredDescriptionDefault
stopNoSet to true to cancel an active typing indicator (default: false = start typing)
group_idNoGroup ID (base64) to show typing in a group
recipientNoPhone number in E.164 format

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already declare the safety profile (non-destructive, idempotent, open-world), and the description layers on non-obvious behavior: the indicator auto-expires in ~15s, is cleared on send, is silently ignored when the recipient has disabled indicators, contacts Signal's servers, and stores nothing. It even states the return value without an output schema.

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?

Front-loaded with the core purpose, then parameter semantics, then behavioral caveats and the return shape. Dense but every sentence carries operational information; nothing is redundant padding.

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

Completeness5/5

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

For a small cosmetic tool with no output schema, the description covers purpose, parameter interpretation, lifecycle, edge cases, and the literal return payload. Nothing an agent needs to call it correctly is missing.

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

Parameters4/5

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

Schema coverage is 100% so the baseline is 3, but the description adds meaning the schema lacks: it clarifies that recipient and group_id are alternatives ('at least one is required') even though the schema marks zero required params, and that group_id comes from list_groups. The '~15 second' expiry and silent-ignore behavior also disambiguate stop's value.

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 ('show or cancel') plus the resource ('typing… indicator') and its scope (DM or group), which no sibling tool covers. An agent can distinguish it immediately from send_message/send_group_message without opening a schema.

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

Usage Guidelines5/5

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

Gives explicit when-to-use guidance ('use before send_message / send_group_message in an automated reply'), an explicit when-not ('stop is rarely needed', 'one call per message is enough — don't loop'), and points to sibling tools by name. Routing is unambiguous.

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

set_webhookA
Idempotent

Save or clear the webhook URL that signal-mcp's background receiver (signal-mcp receive --watch, run by install-service) POSTs every incoming message to. url (optional): an http(s) URL such as 'http://localhost:5678/webhook/signal'; omit it or pass null/empty to clear. Stored in ~/.local/share/signal-mcp/webhook.json; the receiver reads it at startup, so restart the service for a change to apply. The SIGNAL_MCP_WEBHOOK environment variable overrides it. Payload: JSON {event: 'message', timestamp, sender, recipient, group_id, body, quote_id, attachments, is_read, receipt_type, expires_in_seconds, view_once}. Returns {status: 'webhook set', url} or {status: 'webhook cleared'}. Use get_webhook to check the value in effect.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoWebhook URL to POST to (e.g. 'http://localhost:5678/webhook/signal'). Omit or pass null to clear.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare mutating, idempotent, non-destructive. The description goes well beyond: storage path (~/.local/share/signal-mcp/webhook.json), that the receiver reads it only at startup, that SIGNAL_MCP_WEBHOOK overrides it, the exact JSON payload shape, and the two possible return objects.

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-loads the core action, then layers clearing semantics, storage/lifecycle, override behavior, payload and return shape. Dense but every sentence carries operational information; the payload field list is the only slightly expendable element.

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

Completeness5/5

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

No output schema exists, yet the description spells out both return objects, the file it writes, the restart requirement, and the env-var override — everything needed to call it correctly and interpret the result.

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

Parameters4/5

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

Schema coverage is 100% so the baseline is 3, but the description adds meaning the schema lacks: that an empty string (not just null/omission) also clears the webhook, plus the concrete localhost URL format used by the receiver.

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+resource: saving or clearing the webhook URL that signal-mcp's background receiver POSTs messages to. It names the sibling (get_webhook) that retrieves rather than mutates, so an agent can separate the two without opening a schema.

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

Usage Guidelines5/5

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

Explicitly covers both branches: provide a URL to set, omit/null/empty to clear, and use get_webhook to inspect the effective value. It also names the operational precondition (restart the service for the change to apply).

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

start_change_numberA

Step 1 of moving this Signal account to a new phone number: asks Signal to send a verification code to the new number. number (required): the new number in E.164 format, e.g. +12025551234; voice (boolean, default false): deliver the code by voice call instead of SMS; captcha (optional): a captcha token, needed only when a previous attempt failed with a captcha-required error; solve one at https://signalcaptchas.org/registration/generate.html and pass the resulting signalcaptcha:// token. Primary device only: on a linked signal-cli setup it fails with 'This command doesn't work on linked devices'. The account stays on the old number until finish_change_number succeeds. Rate limits are returned as errors. Returns {status: 'verification code sent', number}. Then call finish_change_number with the same number and the received code.

ParametersJSON Schema
NameRequiredDescriptionDefault
voiceNoRequest code via voice call instead of SMS (default: false)
numberYesNew phone number in E.164 format (e.g. +12025551234)
captchaNoCaptcha token (required only if Signal demands it)

TDQS

A4.9/5.0
Behavior5/5

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

Goes well beyond the annotations (readOnlyHint=false, idempotentHint=false, destructiveHint=false, openWorldHint=true) by disclosing that the account stays on the old number until finish_change_number succeeds, that rate limits surface as errors, that linked devices will fail with a specific message, and the exact return payload.

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?

Information-dense and front-loaded with the purpose, then constraints, then next step. It is a long single block with semicolon-chained parameter notes, which slightly hurts scannability, but nearly every clause carries load-bearing detail.

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

Completeness5/5

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

With no output schema, the description supplies the return shape ({status: 'verification code sent', number}) and the full two-step workflow, device prerequisites, and error conditions. An agent has everything needed to invoke and sequence this tool.

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 already 100%, but the description adds real meaning on top: the captcha token is only needed after a captcha-required error, plus the URL to mint one and the signalcaptcha:// token format — operational detail absent from the schema.

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

Purpose5/5

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

Opens with a precise verb+resource: 'Step 1 of moving this Signal account to a new phone number: asks Signal to send a verification code to the new number.' It explicitly positions itself as the first half of a two-step flow, making it distinguishable from the sibling finish_change_number.

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

Usage Guidelines5/5

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

States when to call it, names the follow-up call ('Then call finish_change_number with the same number and the received code'), and gives explicit exclusions: primary device only, fails on linked signal-cli setups. The captcha branch is conditioned on a specific prior error.

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

store_statsA
Read-onlyIdempotent

Report statistics about signal-mcp's local message database (~/.local/share/signal-mcp/messages.db). Returns {total_messages, unread_messages (incoming only), db_size_bytes, oldest, newest} with oldest/newest as ISO datetimes or null when empty. Read-only, local only, no daemon needed. Use it to check whether history has been imported (import_desktop / sync_desktop) or before cleaning up with prune_store, delete_local_messages or clear_local_store.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds real context beyond that: local-only, no daemon required, the on-disk path, and the semantics that unread counts incoming messages only and oldest/newest are null when the store is empty.

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

Conciseness5/5

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

Three sentences: purpose, return contract, then usage routing. Front-loaded and every sentence earns its place with no redundancy.

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

Completeness5/5

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

With no output schema, the description carries the return-value burden and does so fully — it names every field and the null semantics. Combined with the annotations and zero parameters, an agent has everything needed to call it correctly.

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?

The tool takes no parameters, so per the rubric the baseline is 4. The description correctly spends no space on parameter syntax and instead documents the return shape, which is the useful information here.

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 ('Report statistics about signal-mcp's local message database') and even names the exact DB path. It enumerates the returned fields, so an agent knows precisely what it produces and can distinguish it from siblings like get_unread or list_conversations.

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

Usage Guidelines5/5

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

Gives explicit when-to-use conditions: verify history import status before/after import_desktop or sync_desktop, and check store state before destructive cleanup via prune_store, delete_local_messages or clear_local_store. Both the alternatives and the selecting conditions are named.

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

submit_rate_limit_challengeA

Lift a Signal rate limit on sending by submitting a proof-of-humanity challenge. Use it when a send fails with a rate-limit / proof-required error that includes a challenge token. challenge (required): the challenge token from that error; captcha (required): the token from solving the captcha at https://signalcaptchas.org/challenge/generate.html. Talks to Signal's servers; a rejected captcha returns an error and you need a fresh one. Returns {status: 'challenge submitted'}; then retry the failed send. For a captcha needed while changing number, pass it to start_change_number instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
captchaYesSolved captcha token from the Signal captcha page
challengeYesChallenge token from the rate-limit error

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already flag openWorldHint=true and idempotentHint=false, and the description reinforces the external call ('Talks to Signal's servers') while adding behavior annotations do not carry: a rejected captcha returns an error and requires a fresh one, and the caller must retry the failed send afterward. Error and retry semantics are precisely the value-add expected here.

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?

Front-loads the purpose, then trigger, then parameters, then error behavior and return value, then the sibling alternative. Every sentence carries load with no filler; parentheticals are compact.

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

Completeness5/5

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

No output schema exists, but the description discloses the return value ({status: 'challenge submitted'}) and the required follow-up action (retry the failed send), plus failure behavior. For a two-parameter, single-purpose tool this leaves nothing an agent needs missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description goes beyond the schema by stating where each token originates: the challenge token 'from that error' and the captcha token from solving the captcha at a specific URL. That origin/provenance detail is genuinely useful for correct invocation.

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+resource ('Lift a Signal rate limit on sending') and the mechanism (submitting a proof-of-humanity challenge), which no sibling tool offers. An agent can immediately tell this apart from send_message or start_change_number.

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

Usage Guidelines5/5

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

Gives an explicit trigger ('when a send fails with a rate-limit / proof-required error that includes a challenge token') and an explicit exclusion/alternative ('For a captcha needed while changing number, pass it to start_change_number instead'). This is exactly the when/when-not/alternative guidance the dimension rewards.

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

sync_desktopA
Idempotent

Incrementally import new messages from Signal Desktop into signal-mcp's local store: only messages newer than the last sync (with a 60-second overlap) are read, so repeat calls are fast. No parameters. The first call imports everything, like import_desktop. Same requirements as import_desktop: sqlcipher, Signal Desktop installed, and Keychain (macOS) or secret-tool (Linux) access to its key. Only writes to the local store; duplicates are skipped. Returns the import_desktop fields {imported, skipped, total, max_ts_ms, platform, source} plus since (ISO datetime of the lower bound, null on first run) and incremental (boolean). Use import_desktop only for a deliberate full re-scan.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already disclose the safety profile (readOnlyHint=false, idempotentHint=true, destructiveHint=false, openWorldHint=false), and the description adds valuable context beyond them: only writes to the local store, duplicates are skipped, a 60-second overlap is used, first-run behavior is described, and external prerequisites are listed. It also describes return fields including since and incremental, so behavior is unusually transparent.

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

Conciseness5/5

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

The description is dense but front-loaded with the core incremental-import behavior, then adds requirements, side effects, and return shape in a logical order. Every sentence carries useful operational information and none is redundant.

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

Completeness5/5

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

Given the lack of an output schema, the description compensates by naming the returned fields and their meaning, including since and incremental. It also covers prerequisites, local-write-only behavior, and the relationship to import_desktop, leaving no major gap for correct invocation.

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

Parameters4/5

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

The tool has zero parameters, so there is no parameter schema to interpret; the description explicitly states 'No parameters,' which is appropriate. This meets the baseline for a parameterless tool and adds no misleading detail.

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

Purpose5/5

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

The description states a specific verb and resource ('Incrementally import new messages from Signal Desktop into signal-mcp's local store') and immediately distinguishes the operation from import_desktop by emphasizing incremental scope. An agent can identify what the tool does and how it differs from its closest sibling without opening any schema.

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

Usage Guidelines5/5

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

It gives explicit when-to-use context: repeat calls are fast because only messages newer than the last sync are read, while the first call imports everything like import_desktop. It also gives a direct alternative rule: 'Use import_desktop only for a deliberate full re-scan.'

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

terminate_groupA
DestructiveIdempotent

DESTRUCTIVE AND IRREVERSIBLE: permanently terminate a Signal group FOR ALL MEMBERS; afterwards nobody can send messages or start calls in it. Requires admin rights. To just exit the group yourself, use leave_group. group_id (required, from list_groups). confirm (required) must be true, otherwise nothing happens and an error is returned; only set it after the user explicitly asked to end the group for everyone. Returns status and group_id.

ParametersJSON Schema
NameRequiredDescriptionDefault
confirmYesMust be true to proceed — prevents accidental termination
group_idYesGroup ID to terminate (get from list_groups)

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already flag destructiveHint/readOnlyHint, but the description goes well beyond them: irreversible permanence, effect on all members, inability to send messages or start calls afterward, admin-rights requirement, and the exact behavior of the confirm gate (no-op plus error if not true). This is rich behavioral context the annotations do not carry.

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?

Front-loaded with the DESTRUCTIVE AND IRREVERSIBLE warning, then prerequisites, then the sibling alternative, then parameter semantics. Dense but every clause earns its place with no redundancy.

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

Completeness5/5

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

For a destructive mutation tool with no output schema, the description covers consequences, authorization, the confirmation gate, the alternative sibling, and even the return shape (status and group_id). Nothing an agent needs to call it safely is missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds value: it ties group_id to list_groups and, more importantly, defines the policy for confirm (must be true, otherwise nothing happens and an error is returned; only set after an explicit user request). That goes beyond the schema's generic 'prevents accidental termination'.

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 (terminate) and resource (Signal group), plus scope (FOR ALL MEMBERS), and explicitly contrasts with the sibling leave_group. An agent can distinguish it from leave_group, update_group, and delete_message without opening any schema.

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

Usage Guidelines5/5

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

Explicit when-to-use (end the group for everyone, requires admin rights), when-not (use leave_group to exit yourself), and a policy constraint that confirm should only be set after the user explicitly asked. Alternatives and exclusions are named outright.

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

terminate_pollA
Destructive

Close a poll you created so no more votes are accepted; participants see it as ended with final results. Irreversible. Use vote_poll to vote, create_poll to start a new one. Only the creator can terminate. target_author: your own E.164 number (accepted for symmetry with vote_poll; only the timestamp is sent); target_timestamp: ms timestamp of the poll (from create_poll or get_conversation). Give recipient (E.164) for a DM poll or group_id for a group poll; neither is an error. Contacts Signal's servers. Returns {status: 'poll terminated'}.

ParametersJSON Schema
NameRequiredDescriptionDefault
group_idNoGroup ID for a group poll — provide this OR recipient
recipientNoPhone number for a DM poll — provide this OR group_id
target_authorYesPhone number of the poll creator — must be your own number
target_timestampYesTimestamp of the poll message (from get_conversation)

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and idempotentHint=false, so the safety profile is covered. The description adds real context beyond that: the action is irreversible, participants see final results, only the creator may act, and the call contacts Signal's servers. Strong additive disclosure, though the remote side-effect story could be marginally richer.

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 action and its irreversibility, then routing, then parameter notes, then the return value. Slightly dense but every sentence carries information an agent needs; no filler sentences.

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

Completeness5/5

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

With no output schema, the description supplies the return shape ({status: 'poll terminated'}), the permission constraint, and the DM-vs-group addressing rule. For a destructive 4-parameter tool this covers everything needed to call it correctly.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description goes beyond the schema by explaining the odd target_author semantics ('accepted for symmetry with vote_poll; only the timestamp is sent'), the source of target_timestamp (create_poll or get_conversation), and that supplying neither recipient nor group_id is not an error.

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 (terminate) and resource (poll) with the scope of the effect: closing a poll you created so no more votes are accepted. It explicitly distinguishes itself from the two closest siblings, vote_poll and create_poll, so an agent can route correctly without reading either schema.

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

Usage Guidelines5/5

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

Gives explicit alternates with conditions ('Use vote_poll to vote, create_poll to start a new one') and a hard precondition ('Only the creator can terminate'). Nothing about when to choose this tool is left to inference.

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

trust_identityA
Idempotent

Mark a contact's identity key as trusted so sending to them works again after their safety number changed (e.g. they reinstalled Signal). number (required, E.164). safety_number (optional): the safety number or fingerprint you verified in person or by call, as shown by list_identities; only that key is trusted and it becomes TRUSTED_VERIFIED. Without safety_number ALL known keys for the number are trusted unverified — this unblocks delivery but skips verification, so prefer passing it. Changes local trust only; the contact is not notified. Fails if the number or safety number does not match. Returns status 'trusted' and number.

ParametersJSON Schema
NameRequiredDescriptionDefault
numberYesPhone number (E.164) whose identity key to trust
safety_numberNoSafety number or fingerprint you verified (from list_identities); omit to trust all known keys unverified

TDQS

A4.9/5.0
Behavior5/5

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

Beyond the annotations (readOnlyHint=false, idempotentHint=true, destructiveHint=false), the description discloses that trust is local-only, the contact is not notified, the call fails on mismatch, and it returns status 'trusted' plus the number. It also explains the state difference between the verified and unverified paths (TRUSTED_VERIFIED vs unverified), which annotations cannot convey.

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

Conciseness4/5

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

Dense and front-loaded: purpose and trigger first, then parameter semantics, then side effects and return. Every sentence carries information, though it is a single long paragraph that could be broken up for faster scanning.

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

Completeness5/5

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

For a 2-parameter mutation with no output schema, it covers prerequisites (verification via list_identities), failure modes, side effects, and return values. Nothing an agent needs to call it correctly is missing.

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 already 100%, yet the description adds real meaning: E.164 format, that safety_number scopes trust to only that key and yields TRUSTED_VERIFIED, and that omitting it trusts ALL known keys unverified. That consequence-of-omission detail is not derivable from the schema.

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

Purpose5/5

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

States a precise verb+resource ('Mark a contact's identity key as trusted') and the exact condition that motivates it (safety number changed, e.g. reinstall). It is clearly distinguishable from sibling tools like list_identities, which it names as the source of the safety number.

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

Usage Guidelines5/5

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

Explicitly says when to use it (to restore sending after a safety number change), when to prefer the verified path ('prefer passing it'), and what the fallback does. It also names the upstream tool (list_identities) the agent should consult first.

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

unblock_contactA
Idempotent

Unblock a previously blocked contact so their messages and calls reach you again. number (required, E.164). Only works when signal-mcp is the account's primary device — fails with 'This command doesn't work on linked devices' if signal-mcp was set up via signal-cli link. The contact is not notified; unblocking also accepts their message request (your profile is shared with them again) and syncs to your linked devices. Unblocking a contact that is not blocked is a no-op. Use list_contacts with blocked=true to see who is blocked, block_contact to block again. Returns status 'unblocked' and number.

ParametersJSON Schema
NameRequiredDescriptionDefault
numberYesPhone number to unblock (E.164 format)

TDQS

A4.8/5.0
Behavior5/5

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

Annotations give the safety profile (non-readOnly, non-destructive, idempotent, open-world), and the description adds substantial context beyond them: the primary-device prerequisite and its exact failure mode, that the contact is not notified, that unblocking accepts their message request and re-shares the profile, and that changes sync to linked devices.

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

Conciseness4/5

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

Front-loaded with the core action and effect, then the prerequisites and side effects. Dense but every sentence carries information; the only mild cost is that the caveats are packed into one long paragraph.

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

Completeness5/5

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

No output schema exists, but the description supplies the return value ('status unblocked and number'), the failure mode, the side effects, and the alternatives. An agent has everything needed to invoke and interpret it.

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?

Only one parameter and schema coverage is 100%, so the schema already documents 'number (E.164 format)'. The description reinforces the E.164 requirement but adds no syntax beyond that, which is appropriate for a single-param tool.

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 (unblock) and resource (contact) plus the immediate effect ('so their messages and calls reach you again'). It is clearly distinguished from its sibling block_contact, which it names directly.

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

Usage Guidelines5/5

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

Explicitly routes the agent: use list_contacts with blocked=true to find blocked contacts, block_contact to reverse the action. It also states the no-op case for unblocking a non-blocked contact, leaving nothing to inference.

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

unpin_messageA
Idempotent

Remove a pinned message from the top of a DM or group conversation for all participants; the message itself stays. Use pin_message to pin. target_author: E.164 number of the pinned message's sender; target_timestamp: its ms timestamp (message id in get_conversation). Give recipient (E.164) for a DM or group_id for a group; neither is an error. Contacts Signal's servers; repeating has no further effect. Returns {status: 'message unpinned'}.

ParametersJSON Schema
NameRequiredDescriptionDefault
group_idNoGroup ID for group conversations — provide this OR recipient
recipientNoPhone number for DM conversations — provide this OR group_id
target_authorYesPhone number of the message author (E.164)
target_timestampYesTimestamp of the pinned message (from get_conversation)

TDQS

A3.9/5.0
Behavior4/5

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

Adds real behavioral context beyond annotations: 'the message itself stays' clarifies non-destructive scope, 'for all participants' states the effect's reach, 'Contacts Signal's servers' matches openWorldHint, and 'repeating has no further effect' explains the idempotentHint. The idempotency point overlaps the annotation but is explained rather than merely repeated.

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 purpose, then packed into a compact semicolon-delimited sentence carrying routing rules and the return value. Dense but every clause carries information; no filler.

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

Completeness4/5

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

For a mutation with no output schema, the description covers effect scope, non-destructiveness, server contact, idempotency, and even the return value {status: 'message unpinned'}. Only auth/permission prerequisites are unaddressed, a minor gap given the annotation profile.

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

Parameters3/5

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

Schema coverage is 100%, so the schema already documents all four parameters, including E.164 format and get_conversation provenance. The description mostly restates these ('E.164 number', 'its ms timestamp (message id in get_conversation)'), adding only the 'ms' unit precision, so baseline 3 applies.

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

Purpose4/5

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

States a specific verb+resource ('Remove a pinned message from the top of a DM or group conversation for all participants') and clarifies the message itself is preserved. It names pin_message as the inverse but does not differentiate from the sibling remove_pin, leaving a small ambiguity about which removal tool applies.

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

Usage Guidelines4/5

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

Explicitly routes to pin_message for the opposite operation and tells the agent the conversation-selector rule ('Give recipient for a DM or group_id for a group'), so context is clear. No when-not guidance and no mention of remove_pin, so it falls short of full alternative coverage.

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

update_accountA
DestructiveIdempotent

Change account attributes stored on Signal's servers for this account. All six parameters are optional and only the ones you pass are sent: device_name (string) renames this device as shown in list_devices on your other devices; discoverable_by_number (boolean) whether people who have your number can find you on Signal; number_sharing (boolean) whether your phone number is shown to people you message; unrestricted_unidentified_sender (boolean) true lets anyone, not only contacts, send you sealed-sender messages; username (string, without @) claims a Signal username; delete_username (boolean) removes the current one and takes precedence over username if both are given. Takes effect immediately on the real account; setting a username that is taken or invalid fails with an error. Returns {status: 'account updated'} (the resulting username is not echoed). Use update_configuration for read receipts, typing indicators and link previews, update_profile for your name, about text and avatar.

ParametersJSON Schema
NameRequiredDescriptionDefault
usernameNoSet a Signal username (without @) as an alias for your number
device_nameNoName for this device shown in linked devices list
number_sharingNoShare your phone number when sending messages
delete_usernameNoDelete your current Signal username
discoverable_by_numberNoAllow others to find your account by phone number
unrestricted_unidentified_senderNoAllow sealed-sender messages from anyone (not just contacts)

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already cover the safety profile (destructiveHint=true, idempotentHint=true), and the description adds substantial context beyond them: changes take effect immediately on the real account, invalid/taken usernames fail with an error, delete_username takes precedence over username, and the return payload is {status: 'account updated'} with the username not echoed.

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 purpose and the alternative-tool routing are front-loaded, and every sentence carries information. It is, however, a dense unbroken block rather than a structured parameter list, which slightly hurts scanability for a six-parameter tool.

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

Completeness5/5

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

Despite having no output schema, the description states the exact return shape and the notable omission (username not echoed), covers error behavior, precedence, and cross-tool routing. Nothing an agent needs to call this correctly is missing.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3, but the description goes further: it explains what each flag means in user terms (device_name appears in list_devices on other devices; discoverable_by_number governs number-based discovery), specifies the username format (without @), and documents the delete_username-over-username precedence rule that the schema does not.

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 ('Change account attributes stored on Signal's servers for this account') and explicitly routes the agent away from siblings: update_configuration for receipts/typing/link previews and update_profile for name/about/avatar. An agent can distinguish it from every related tool without opening a schema.

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

Usage Guidelines5/5

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

Names the two alternatives and the exact conditions that select them, plus notes that all six parameters are optional and only passed ones are sent. This tells the agent both when to use this tool and when to use a neighbor instead.

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

update_configurationA
Idempotent

Change account-wide messaging settings and sync them to your linked devices. All four booleans are optional; omit any you do not want to change, and a call with none is a no-op: read_receipts whether senders are told when you have read their messages; typing_indicators whether contacts see you typing; link_previews whether URLs in outgoing messages get previews; unidentified_delivery_indicators whether sealed-sender delivery icons are shown. Primary device only: on a linked signal-cli setup it fails with 'This command doesn't work on linked devices'. Returns {status: 'updated'}. signal-cli cannot read the current values back, so track what you set. Use update_account for discoverability, number sharing and username; update_profile for name and avatar.

ParametersJSON Schema
NameRequiredDescriptionDefault
link_previewsNoEnable/disable link previews in messages
read_receiptsNoEnable/disable sending read receipts
typing_indicatorsNoEnable/disable sending typing indicators
unidentified_delivery_indicatorsNoShow/hide sealed sender indicators

TDQS

A4.8/5.0
Behavior5/5

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

Goes well beyond the annotations by disclosing linked-device sync, the exact failure mode on linked signal-cli setups, the no-op behavior, the return value ({status: 'updated'}), and the fact that current values cannot be read back so callers must track state. The idempotentHint/destructiveHint annotations don't cover any of this operational context.

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-loads the core action and scope, then elaborates each boolean and the constraints. Dense and mostly waste-free, though the per-boolean clarifications and routing notes make it longer than strictly necessary.

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

Completeness5/5

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

For a no-required-param mutation tool, it covers scope, optionality, failure modes, return value, and sibling routing, leaving nothing an agent needs to call it correctly. No output schema exists, yet the return shape is still disclosed.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning over the terse schema text — e.g. 'read_receipts whether senders are told when you have read their messages' and the sealed-sender explanation for unidentified_delivery_indicators. It also reinforces optionality, which the schema does not state.

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+resource ('Change account-wide messaging settings') and scopes it to the four booleans it mutates. It explicitly differentiates from siblings update_account and update_profile by naming the settings each one handles.

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

Usage Guidelines5/5

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

Explicitly explains optionality ('omit any you do not want to change'), the no-op case, the primary-device-only constraint, and precisely when to reach for update_account vs update_profile instead. An agent needs no inference to choose correctly.

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

update_contactA
Idempotent

Set your private local name, nickname or note for another contact; it is synced to your own linked devices and never shown to the contact. To change your own public profile use update_profile; to block or delete a contact use block_contact or remove_contact. number (required, E.164). Pass at least one of: name (full display name; stored as given name and clears the family name unless family_name is also given), given_name, family_name, nick_given_name, nick_family_name (nickname shown instead of their profile name), note (private note). Fails if none is given or the number is not registered on Signal. Returns status, number and name. For a disappearing-message timer use set_expiration_timer.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoDisplay name to set
noteNoPrivate note about the contact
numberYesPhone number in E.164 format
given_nameNoContact given name
family_nameNoContact family name
nick_given_nameNoNickname given name
nick_family_nameNoNickname family name

TDQS

A4.9/5.0
Behavior5/5

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

Annotations cover the safety profile (readOnly=false, destructive=false, idempotent=true), and the description adds non-obvious behavior on top: the change is local-only, synced to your linked devices, never visible to the contact, and setting 'name' silently clears family_name unless family_name is also supplied. That side-effect disclosure is exactly the kind of trait structured fields cannot convey.

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

Conciseness4/5

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

Front-loaded with the core purpose and alternatives, and every sentence carries information. Slightly dense with nested parentheticals in the parameter list, but appropriate for a 7-parameter tool in a crowded sibling namespace.

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

Completeness5/5

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

With no output schema, the description supplies the return shape ('status, number and name'), the failure modes, the exclusivity constraint, and the local-only scope. Nothing needed to invoke it correctly is missing.

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 100% (baseline 3), but the description goes well beyond it: it supplies the E.164 format, the cross-field rule that at least one optional field must be passed, and semantic distinctions the schema lacks (name vs. given/family name interaction, nickname 'shown instead of their profile name').

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 (set) and resource (private local name/nickname/note for another contact) and immediately contrasts it with update_profile, block_contact and remove_contact. An agent can distinguish it from every nearby sibling without opening a schema.

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

Usage Guidelines5/5

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

Explicitly routes alternatives: update_profile for your own public profile, block_contact/remove_contact for blocking or deleting, set_expiration_timer for timers. It also states the precondition ('Pass at least one of...') and two failure conditions (no field given, number not registered).

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

update_deviceA
Idempotent

Rename a device on your Signal account; the name shows in every device's Linked Devices list. device_id (required, integer from list_devices); name (required): the new label. Renaming the device signal-mcp itself runs on works everywhere; renaming any other device only works when signal-mcp is the account's primary device — otherwise it fails with 'This command doesn't work on linked devices'. Does not affect messaging. Returns status, device_id and name. To unlink a device use remove_device; to change your profile name use update_profile.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesNew display name for the device
device_idYesDevice ID (get from list_devices)

TDQS

A4.6/5.0
Behavior5/5

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

Goes well beyond the annotations (readOnlyHint=false, idempotentHint=true, destructiveHint=false, openWorldHint=true) by disclosing the side effect (visible in every device's Linked Devices list), the primary-device precondition for renaming other devices, that messaging is unaffected, and the returned fields (status, device_id, name).

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 purpose, then precondition, then scope note and alternatives in a tight sequence with no filler. It is dense and slightly long, but nearly every clause carries actionable information (the quoted error string is the only borderline item).

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

Completeness5/5

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

For a two-parameter mutation with no output schema, the description covers purpose, precondition, failure mode, side effects, and return fields, and routes to alternatives. Nothing an agent needs in order to call it correctly is missing.

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

Parameters3/5

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

Schema description coverage is 100%, so both parameters are already documented. The description restates device_id as coming from list_devices and name as the new label, adding only marginal context beyond the schema, so the baseline 3 applies.

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

Purpose5/5

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

States a specific verb+resource ('Rename a device on your Signal account') and immediately scopes what the name affects (the Linked Devices list on every device). It is clearly distinguishable from siblings like update_profile or remove_device, which it names explicitly.

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

Usage Guidelines5/5

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

Gives explicit routing: use remove_device to unlink, use update_profile to change profile name. It also states the precise precondition under which the tool works versus fails, including the exact error text 'This command doesn't work on linked devices'.

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

update_groupA
DestructiveIdempotent

Change an existing group's details, membership, admins, invite link, permissions or timer; only the fields you pass change. group_id (required, from list_groups). name, description: new text. avatar: local image path inside the allowed send folders. add_members / remove_members / add_admins / remove_admins / ban_members / unban_members: lists of E.164 numbers. expiration_seconds: disappearing-message timer, 0 disables. link_mode: 'enabled' (anyone with the link joins), 'enabled-with-approval', 'disabled', or 'reset' (same as reset_link=true, which issues a new link and invalidates the old one). permission_add_member, permission_edit_details, permission_send_messages: 'every-member' or 'only-admins' (only-admins sending = announcement group). member_label / member_label_emoji set ONLY YOUR OWN label in this group (the tag next to your name); you cannot set another member's label. Changes apply immediately and every member gets a group update; removals and bans are not undone automatically. Admin rights are needed for most changes, depending on the group's permissions. Returns status and group_id. Use send_group_message to post, leave_group to exit.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoNew group name
avatarNoLocal image file path for the new group avatar (must be inside the allowed send folders)
group_idYesGroup ID to update (get from list_groups)
link_modeNoInvite link mode: 'disabled', 'enabled', 'enabled-with-approval', or 'reset' to generate a new link
add_adminsNoPhone numbers (E.164) to promote to admin
reset_linkNoGenerate a new invite link, invalidating the old one
add_membersNoPhone numbers (E.164) to add
ban_membersNoPhone numbers (E.164) to ban from (re)joining the group
descriptionNoNew group description
member_labelNoYOUR OWN member label in this group (not other members')
remove_adminsNoPhone numbers (E.164) to demote from admin
unban_membersNoPhone numbers (E.164) to remove from the ban list
remove_membersNoPhone numbers (E.164) to remove
expiration_secondsNoDisappearing message timer in seconds (0 to disable)
member_label_emojiNoEmoji for YOUR OWN member label
permission_add_memberNoWho may add new members
permission_edit_detailsNoWho may edit group name, description, avatar, timer
permission_send_messagesNoWho may send messages ('only-admins' = announcement group)

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already mark this as a destructive, non-read-only, open-world mutation, but the description adds substantial context beyond them: changes apply immediately, all members receive a group update, removals and bans are not automatically undone, admin rights are typically required, and 'reset' invalidates the old link. This is exactly the extra behavioral detail the annotations cannot convey.

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

Conciseness4/5

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

Purpose and required-parameter reminder are front-loaded, and for 18 parameters nearly every clause carries needed meaning. It is delivered as one dense run-on paragraph, which slightly hurts scannability, but there is very little filler to cut.

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

Completeness5/5

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

Despite 18 parameters and no output schema, the description covers semantics for every notable field, side effects, permission requirements, and even the return shape ('Returns status and group_id'). An agent has everything needed to call it correctly.

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

Parameters4/5

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

With 100% schema coverage, the baseline is 3, but the description genuinely elaborates on the schema: it explains each link_mode value, translates permission_send_messages 'only-admins' into 'announcement group,' clarifies that expiration_seconds 0 disables the timer, and stresses that member_label applies ONLY to the caller's own label. These interpretations go beyond the bare property descriptions.

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 ('Change an existing group's details, membership, admins, invite link, permissions or timer') and immediately scopes it with 'only the fields you pass change.' This clearly separates it from create_group, leave_group, and terminate_group without needing to open any schema.

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

Usage Guidelines4/5

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

Explicitly routes to siblings: 'Use send_group_message to post, leave_group to exit,' and notes group_id comes from list_groups. It also prescribes prerequisites ('Admin rights are needed for most changes'). It does not, however, distinguish itself from terminate_group or compare against create_group, so it stops short of full when/when-not guidance.

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

update_profileA
Idempotent

Change your own Signal profile, which is uploaded to Signal's servers and seen by people you share your profile with. Only the fields you pass change. name: display name (alias of given_name; given_name wins if both are set). given_name / family_name: the two parts of your profile name. about: bio text; about_emoji: emoji shown next to it. mobilecoin_address: base64-encoded MobileCoin public address. avatar_path: local image file (JPEG or PNG) inside the allowed send folders (SIGNAL_MCP_SEND_ROOTS), no hidden paths. remove_avatar (default false): clear the current photo. Returns status 'profile updated'. To label someone else locally use update_contact; to rename a linked device use update_device; for account settings use update_account.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoDisplay (given) name to set; alias of given_name
aboutNoAbout/bio text
given_nameNoProfile given name
about_emojiNoEmoji shown next to the about text
avatar_pathNoLocal JPEG/PNG path inside the allowed send folders (SIGNAL_MCP_SEND_ROOTS)
family_nameNoProfile family name
remove_avatarNoRemove current avatar
mobilecoin_addressNoMobileCoin address (base64)

TDQS

A4.6/5.0
Behavior4/5

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

With annotations already declaring readOnly=false, destructive=false, idempotent=true and openWorld=true, the description still adds material context: profile data is 'uploaded to Signal's servers and seen by people you share your profile with' (privacy exposure), 'Only the fields you pass change' (partial-update semantics), the return string, and avatar path constraints. It does not detail failure modes for invalid paths, so it stops short of 5.

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

Conciseness4/5

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

Purpose and sibling routing are front-loaded, and there is little waste. However, the parameter walkthrough is delivered as a single dense run-on block rather than being broken out, which slightly hurts scannability for an 8-parameter tool.

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

Completeness5/5

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

For a no-required-parameter mutation tool with no output schema, the definition covers visibility of the change, partial-update behavior, removal semantics, path restrictions, and the return value. An agent has everything needed to invoke it correctly.

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

Parameters4/5

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

Schema coverage is already 100%, but the description adds real meaning beyond it: the name/given_name alias with the precedence rule ('given_name wins if both are set'), remove_avatar's default, and the allowed-roots restriction on avatar_path. That precedence rule in particular is not derivable from the schema.

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

Purpose5/5

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

States a specific verb and resource ('Change your own Signal profile') and immediately scopes it to the caller's own profile versus others. It explicitly names the sibling tools it is not (update_contact, update_device, update_account), so an agent can route correctly without opening any schema.

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

Usage Guidelines5/5

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

Offers explicit alternatives with the condition that selects each: 'To label someone else locally use update_contact; to rename a linked device use update_device; for account settings use update_account.' Nothing is left to inference about when to pick this tool.

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

upload_sticker_packA

Publish a new sticker pack made from your own images to Signal's servers and get a shareable signal.art link. path (required): local path to a manifest.json (with the sticker images next to it) or to a zip containing the manifest and images. The file must be inside an allowed folder (~/Downloads/signal-attachments, ~/Downloads, ~/Desktop, ~/Documents, or the SIGNAL_MCP_SEND_ROOTS list) and not in a hidden folder. The pack is public to anyone with the link and cannot be deleted through this tool. Invalid packs or oversized images return an error. Returns {url}. Use add_sticker_pack to install an existing pack.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesLocal path to manifest.json or a zip containing the sticker pack

TDQS

A4.9/5.0
Behavior5/5

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

Annotations cover the safety profile (readOnlyHint=false, openWorldHint=true, destructiveHint=false), but the description adds what annotations cannot: the pack becomes public to anyone with the link, it cannot be deleted through this tool, invalid or oversized images error out, and the return is {url}. These are consequential, non-obvious behaviors for an irreversible publish action.

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

Conciseness4/5

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

Front-loaded with the purpose, then path rules, side effects, error behavior, and the sibling pointer — every sentence carries weight. It is a dense single paragraph rather than scannable structure, which slightly hurts fast parsing, but there is no filler.

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

Completeness5/5

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

With no output schema, the description supplies the return shape ({url}) and the failure mode (error on invalid/oversized packs). Combined with the visibility and deletion constraints, an agent has everything needed to invoke this correctly and warn the user about permanence.

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 100% for the single path parameter, so the baseline would be 3, but the description materially enriches it: the value may point to a manifest.json (with images beside it) or a zip, and must sit inside an enumerated allowlist of folders while avoiding hidden folders. That is real semantics beyond the schema's one-line type description.

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 ('Publish a new sticker pack... to Signal's servers') plus the concrete outcome (shareable signal.art link). It explicitly distinguishes itself from add_sticker_pack, which installs existing packs rather than publishing new ones, so an agent can route without opening either schema.

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

Usage Guidelines5/5

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

Gives both the positive trigger (publishing your own images as a new pack) and the alternative with its condition ('Use add_sticker_pack to install an existing pack'). The allowed-folder constraint and the hidden-folder exclusion further define when a call will be valid.

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

vote_pollA
Idempotent

Cast or change your vote on an open Signal poll in a DM or group; the vote is visible to participants. Use create_poll to start a poll, terminate_poll to close your own. A poll has no separate id: identify it by target_author (E.164 number of the poll's creator) + target_timestamp (ms timestamp of the poll message, from create_poll or get_conversation). votes: 0-based indices into the poll's options — exactly one for a single-choice poll, all chosen indices at once for multi-select (each call replaces your previous vote). Give recipient (E.164) for a DM poll or group_id for a group poll; neither is an error. Voting on a terminated poll fails. Contacts Signal's servers; a local per-poll counter is incremented so re-votes supersede earlier ones. Returns {status: 'vote sent'}.

ParametersJSON Schema
NameRequiredDescriptionDefault
votesYesOption indices to vote for (0-based). Single item for single-choice polls.
group_idNoGroup ID for a group poll — provide this OR recipient
recipientNoPhone number for a DM poll — provide this OR group_id
target_authorYesPhone number of the poll creator (E.164)
target_timestampYesTimestamp of the poll message (from get_conversation)

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already cover safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=true, openWorldHint=true). Description adds substantial context: vote visibility to participants, replacement semantics for re-votes, server contact, local per-poll counter, and return value. Aligns with annotations (idempotentHint matches re-vote superseding).

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 purpose and alternatives, but dense with multiple clauses in later sentences. Every sentence earns its place, though the description could be slightly trimmed without losing critical information.

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

Completeness5/5

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

No output schema exists, but the description provides the return value. Covers identification, parameter usage, failure conditions, and server interaction. Complete for a voting tool of this complexity.

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 100%, so baseline is 3. However, the description adds meaning beyond schema: identification via target_author + target_timestamp, votes semantics (0-based indices, single-choice vs multi-select, each call replaces previous vote), and DM vs group parameter selection. This significantly enriches parameter understanding.

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+resource: 'Cast or change your vote on an open Signal poll in a DM or group.' Clearly distinguishes from siblings create_poll and terminate_poll, which are named as alternatives.

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

Usage Guidelines5/5

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

Explicitly names create_poll and terminate_poll as alternative tools and their use cases. Also details how to identify the poll, which parameters to provide for DM vs group, and the failure condition (voting on a terminated poll fails).

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 updatesv1.43.0
    • Changedadd_device1 field changed
      • changedInput schema / properties / uri / description
        Previous value: -"Device link URI (from signal-cli link output)"New value: +"Device link URI (sgnl://linkdevice?...) from the new device's QR code or signal-cli link output"
    • Changedfind_contact1 field changed
      • changedInput schema / properties / query / description
        Previous value: -"Name or phone number fragment to search for"New value: +"Case-insensitive fragment of a name, nickname, username or phone number"
    • Changedget_conversation3 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"Max messages to return (default: 50)"New value: +"Max messages to return (default 50, clamped 1-500)"
      • changedInput schema / properties / offset / description
        Previous value: -"Number of messages to skip for pagination (default: 0)"New value: +"Number of newest messages to skip for pagination (default: 0)"
      • changedInput schema / properties / recipient / description
        Previous value: -"Phone number or group ID"New value: +"E.164 phone number for a DM, or group ID (from list_groups)"
    • Changedlist_identities1 field changed
      • changedInput schema / properties / number / description
        Previous value: -"Filter to a specific contact (optional)"New value: +"Only this contact's keys (E.164 phone number); omit for all"
    • Changedmark_as_unread1 field changed
      • changedInput schema / properties / message_ids / description
        Previous value: -"List of message IDs to mark as unread"New value: +"Message id strings as returned by get_conversation, get_unread or search_messages"
    • Changedsearch_messages1 field changed
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum results to return (default 50)"New value: +"Maximum results to return (default 50, clamped 1-500)"
    • Changedsend_message1 field changed
      • addedInput schema / properties / formatting
        Added value: +{
        +  "description": "Convert **bold**, *italic*, ~~strikethrough~~, `monospace`, ||spoiler|| to Signal text formatting. Default false.",
        +  "type": "boolean"
        +}
    • Changedsend_message_request_response2 fields changed
      • changedInput schema / properties / accept / description
        Previous value: -"true to accept and start chatting, false to decline/block"New value: +"true to accept (shares your profile), false to decline (does not block)"
      • changedInput schema / properties / sender / description
        Previous value: -"Phone number of the contact who sent the message request"New value: +"Phone number (E.164) of the contact who sent the message request"
    • Changedsend_read_receipt1 field changed
      • changedInput schema / properties / timestamps / description
        Previous value: -"Timestamps of the messages to mark as read (from get_conversation sent_at/received_at fields)"New value: +"Millisecond timestamps of the messages to acknowledge (the message id in get_conversation)"
    • Changedset_expiration_timer2 fields changed
      • changedInput schema / properties / group_id / description
        Previous value: -"Group ID for a group conversation"New value: +"Group ID (from list_groups) for a group conversation; wins if recipient is also given"
      • changedInput schema / properties / recipient / description
        Previous value: -"Phone number for a direct conversation"New value: +"Phone number (E.164) for a direct conversation"
    • Changedtrust_identity2 fields changed
      • changedInput schema / properties / number / description
        Previous value: -"Phone number to trust"New value: +"Phone number (E.164) whose identity key to trust"
      • changedInput schema / properties / safety_number / description
        Previous value: -"Verified safety number (leave blank to trust all known keys)"New value: +"Safety number or fingerprint you verified (from list_identities); omit to trust all known keys unverified"
    • Changedupdate_group8 fields changed
      • changedInput schema / properties / add_admins / description
        Previous value: -"Phone numbers to promote to admin"New value: +"Phone numbers (E.164) to promote to admin"
      • changedInput schema / properties / add_members / description
        Previous value: -"Phone numbers to add"New value: +"Phone numbers (E.164) to add"
      • changedInput schema / properties / avatar / description
        Previous value: -"Local image file path for the new group avatar"New value: +"Local image file path for the new group avatar (must be inside the allowed send folders)"
      • changedInput schema / properties / ban_members / description
        Previous value: -"Members to ban from (re)joining the group"New value: +"Phone numbers (E.164) to ban from (re)joining the group"
      • changedInput schema / properties / group_id / description
        Previous value: -"Group ID to update"New value: +"Group ID to update (get from list_groups)"
      • changedInput schema / properties / remove_admins / description
        Previous value: -"Phone numbers to demote from admin"New value: +"Phone numbers (E.164) to demote from admin"
      • changedInput schema / properties / remove_members / description
        Previous value: -"Phone numbers to remove"New value: +"Phone numbers (E.164) to remove"
      • changedInput schema / properties / unban_members / description
        Previous value: -"Members to remove from the ban list"New value: +"Phone numbers (E.164) to remove from the ban list"
    • Changedupdate_profile1 field changed
      • changedInput schema / properties / avatar_path / description
        Previous value: -"Path to avatar image file"New value: +"Local JPEG/PNG path inside the allowed send folders (SIGNAL_MCP_SEND_ROOTS)"
  2. 2 tool updatesv1.42.0
    • Changedsend_group_message1 field changed
      • addedInput schema / properties / formatting
        Added value: +{
        +  "description": "Convert **bold**, *italic*, ~~strikethrough~~, `monospace`, ||spoiler|| to Signal text formatting. Default false.",
        +  "type": "boolean"
        +}
    • Changedsend_note_to_self1 field changed
      • changedInput schema / properties / message / description
        Previous value: -"Note text to save. Supports **bold**, ~~strikethrough~~, `monospace`"New value: +"Note text to save. Supports **bold**, *italic*, ~~strikethrough~~, `monospace`, ||spoiler||"
  3. 21 tool updatesv1.40.1
    • Changedcreate_group1 field changed
      • addedInput schema / properties / avatar
        Added value: +{
        +  "description": "Optional local image file path for the group avatar",
        +  "type": "string"
        +}
    • Changedfind_contact1 field changed
      • addedInput schema / properties / all_recipients
        Added value: +{
        +  "default": false,
        +  "description": "Also include recipients that are not in your address book (e.g. members of your groups), with their profile names",
        +  "type": "boolean"
        +}
    • Changedget_attachment1 field changed
      • changedInput schema / properties / filename / description
        Previous value: -"Attachment filename (get from list_attachments)"New value: +"Attachment filename (from list_attachments) or signal-cli attachment id"
    • Changedget_user_status2 fields changed
      • addedInput schema / properties / usernames
        Added value: +{
        +  "description": "List of Signal usernames or username links to check",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "recipients"
        -]
    • Changedleave_group2 fields changed
      • addedInput schema / properties / admins
        Added value: +{
        +  "description": "Members to make admin before leaving — required if you are the only admin",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / delete
        Added value: +{
        +  "description": "Also delete all local group data after leaving",
        +  "type": "boolean"
        +}
    • Changedlist_contacts2 fields changed
      • addedInput schema / properties / all_recipients
        Added value: +{
        +  "default": false,
        +  "description": "Also include recipients that are not in your address book (e.g. members of your groups), with their profile names",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / blocked
        Added value: +{
        +  "description": "true = only blocked contacts, false = only unblocked (omit for all)",
        +  "type": "boolean"
        +}
    • Changedlist_groups1 field changed
      • addedInput schema / properties / group_id
        Added value: +{
        +  "description": "Optional: return only this group",
        +  "type": "string"
        +}
    • Changedreceive_direct5 fields changed
      • addedInput schema / properties / ignore_attachments
        Added value: +{
        +  "default": false,
        +  "description": "Don't download attachments",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / ignore_avatars
        Added value: +{
        +  "default": false,
        +  "description": "Don't download avatars",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / ignore_stickers
        Added value: +{
        +  "default": false,
        +  "description": "Don't download sticker packs",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / ignore_stories
        Added value: +{
        +  "default": false,
        +  "description": "Don't receive story messages",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / max_messages
        Added value: +{
        +  "description": "Return after this many messages (default: no limit)",
        +  "type": "integer"
        +}
    • Changedreceive_messages1 field changed
      • addedInput schema / properties / max_messages
        Added value: +{
        +  "description": "Return after this many messages (default: no limit)",
        +  "type": "integer"
        +}
    • Changedremove_contact2 fields changed
      • addedInput schema / properties / forget
        Added value: +{
        +  "default": false,
        +  "description": "Delete all data for this recipient, including identity keys and sessions",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / hide
        Added value: +{
        +  "default": false,
        +  "description": "Hide the contact but keep its data",
        +  "type": "boolean"
        +}
    • Changedsend_attachment11 fields changed
      • addedInput schema / properties / no_urgent
        Added value: +{
        +  "default": false,
        +  "description": "Send without the urgent flag, so the recipient gets no push notification",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / notify_self
        Added value: +{
        +  "default": false,
        +  "description": "If you are among the recipients, deliver as a normal (notifying) message instead of a silent sync message",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / quote_attachments
        Added value: +{
        +  "description": "Attachments of the quoted message as 'contentType[:filename[:previewFile]]', e.g. 'image/png:photo.png'",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / quote_author
        Added value: +{
        +  "description": "Phone number (E.164) of the author of the message being quoted/replied to",
        +  "type": "string"
        +}
      • addedInput schema / properties / quote_mentions
        Added value: +{
        +  "description": "@mentions inside the quoted text, same shape as mentions: {start, length, author}",
        +  "items": {
        +    "properties": {
        +      "author": {
        +        "type": "string"
        +      },
        +      "length": {
        +        "type": "integer"
        +      },
        +      "start": {
        +        "type": "integer"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / quote_message
        Added value: +{
        +  "description": "Text of the quoted message shown in the quote bubble. Default: looked up in the local store by quote_author + quote_timestamp",
        +  "type": "string"
        +}
      • addedInput schema / properties / quote_text_styles
        Added value: +{
        +  "description": "Styles inside the quoted text as 'start:length:STYLE' (BOLD, ITALIC, SPOILER, STRIKETHROUGH, MONOSPACE)",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / quote_timestamp
        Added value: +{
        +  "description": "Timestamp of the message being quoted/replied to (from get_conversation)",
        +  "type": "integer"
        +}
      • addedInput schema / properties / username
        Added value: +{
        +  "description": "Signal username (e.g. alice.42) or username link, instead of recipient",
        +  "type": "string"
        +}
      • addedInput schema / properties / voice_note
        Added value: +{
        +  "default": false,
        +  "description": "Mark audio attachments as voice notes (played inline in Signal)",
        +  "type": "boolean"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "recipient"
        -]
    • Changedsend_group_attachment9 fields changed
      • addedInput schema / properties / no_urgent
        Added value: +{
        +  "default": false,
        +  "description": "Send without the urgent flag, so the recipient gets no push notification",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / notify_self
        Added value: +{
        +  "default": false,
        +  "description": "If you are among the recipients, deliver as a normal (notifying) message instead of a silent sync message",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / quote_attachments
        Added value: +{
        +  "description": "Attachments of the quoted message as 'contentType[:filename[:previewFile]]', e.g. 'image/png:photo.png'",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / quote_author
        Added value: +{
        +  "description": "Phone number (E.164) of the author of the message being quoted/replied to",
        +  "type": "string"
        +}
      • addedInput schema / properties / quote_mentions
        Added value: +{
        +  "description": "@mentions inside the quoted text, same shape as mentions: {start, length, author}",
        +  "items": {
        +    "properties": {
        +      "author": {
        +        "type": "string"
        +      },
        +      "length": {
        +        "type": "integer"
        +      },
        +      "start": {
        +        "type": "integer"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / quote_message
        Added value: +{
        +  "description": "Text of the quoted message shown in the quote bubble. Default: looked up in the local store by quote_author + quote_timestamp",
        +  "type": "string"
        +}
      • addedInput schema / properties / quote_text_styles
        Added value: +{
        +  "description": "Styles inside the quoted text as 'start:length:STYLE' (BOLD, ITALIC, SPOILER, STRIKETHROUGH, MONOSPACE)",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / quote_timestamp
        Added value: +{
        +  "description": "Timestamp of the message being quoted/replied to (from get_conversation)",
        +  "type": "integer"
        +}
      • addedInput schema / properties / voice_note
        Added value: +{
        +  "default": false,
        +  "description": "Mark audio attachments as voice notes (played inline in Signal)",
        +  "type": "boolean"
        +}
    • Changedsend_group_message14 fields changed
      • addedInput schema / properties / no_urgent
        Added value: +{
        +  "default": false,
        +  "description": "Send without the urgent flag, so the recipient gets no push notification",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / notify_self
        Added value: +{
        +  "default": false,
        +  "description": "If you are among the recipients, deliver as a normal (notifying) message instead of a silent sync message",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / preview_description
        Added value: +{
        +  "description": "Link preview description",
        +  "type": "string"
        +}
      • addedInput schema / properties / preview_image
        Added value: +{
        +  "description": "Local image file for the link preview thumbnail",
        +  "type": "string"
        +}
      • addedInput schema / properties / preview_title
        Added value: +{
        +  "description": "Link preview title (needed for the card to render)",
        +  "type": "string"
        +}
      • addedInput schema / properties / preview_url
        Added value: +{
        +  "description": "URL for a link preview card; the same URL must also appear in the message text",
        +  "type": "string"
        +}
      • addedInput schema / properties / quote_attachments
        Added value: +{
        +  "description": "Attachments of the quoted message as 'contentType[:filename[:previewFile]]', e.g. 'image/png:photo.png'",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedInput schema / properties / quote_author / description
        Previous value: -"Phone number (E.164) of the author of the message being quoted"New value: +"Phone number (E.164) of the author of the message being quoted/replied to"
      • addedInput schema / properties / quote_mentions
        Added value: +{
        +  "description": "@mentions inside the quoted text, same shape as mentions: {start, length, author}",
        +  "items": {
        +    "properties": {
        +      "author": {
        +        "type": "string"
        +      },
        +      "length": {
        +        "type": "integer"
        +      },
        +      "start": {
        +        "type": "integer"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / quote_message
        Added value: +{
        +  "description": "Text of the quoted message shown in the quote bubble. Default: looked up in the local store by quote_author + quote_timestamp",
        +  "type": "string"
        +}
      • addedInput schema / properties / quote_text_styles
        Added value: +{
        +  "description": "Styles inside the quoted text as 'start:length:STYLE' (BOLD, ITALIC, SPOILER, STRIKETHROUGH, MONOSPACE)",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedInput schema / properties / quote_timestamp / description
        Previous value: -"Timestamp of the quoted message (from get_conversation)"New value: +"Timestamp of the message being quoted/replied to (from get_conversation)"
      • addedInput schema / properties / story_author
        Added value: +{
        +  "description": "Phone number of the story's author, to reply to a story",
        +  "type": "string"
        +}
      • addedInput schema / properties / story_timestamp
        Added value: +{
        +  "description": "Timestamp of the story being replied to",
        +  "type": "integer"
        +}
    • Changedsend_message16 fields changed
      • addedInput schema / properties / end_session
        Added value: +{
        +  "default": false,
        +  "description": "Reset the session with this contact instead of sending a message",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / no_urgent
        Added value: +{
        +  "default": false,
        +  "description": "Send without the urgent flag, so the recipient gets no push notification",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / notify_self
        Added value: +{
        +  "default": false,
        +  "description": "If you are among the recipients, deliver as a normal (notifying) message instead of a silent sync message",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / preview_description
        Added value: +{
        +  "description": "Link preview description",
        +  "type": "string"
        +}
      • addedInput schema / properties / preview_image
        Added value: +{
        +  "description": "Local image file for the link preview thumbnail",
        +  "type": "string"
        +}
      • addedInput schema / properties / preview_title
        Added value: +{
        +  "description": "Link preview title (needed for the card to render)",
        +  "type": "string"
        +}
      • addedInput schema / properties / preview_url
        Added value: +{
        +  "description": "URL for a link preview card; the same URL must also appear in the message text",
        +  "type": "string"
        +}
      • addedInput schema / properties / quote_attachments
        Added value: +{
        +  "description": "Attachments of the quoted message as 'contentType[:filename[:previewFile]]', e.g. 'image/png:photo.png'",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedInput schema / properties / quote_author / description
        Previous value: -"Phone number of the author of the message being quoted/replied to"New value: +"Phone number (E.164) of the author of the message being quoted/replied to"
      • addedInput schema / properties / quote_mentions
        Added value: +{
        +  "description": "@mentions inside the quoted text, same shape as mentions: {start, length, author}",
        +  "items": {
        +    "properties": {
        +      "author": {
        +        "type": "string"
        +      },
        +      "length": {
        +        "type": "integer"
        +      },
        +      "start": {
        +        "type": "integer"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / quote_message
        Added value: +{
        +  "description": "Text of the quoted message shown in the quote bubble. Default: looked up in the local store by quote_author + quote_timestamp",
        +  "type": "string"
        +}
      • addedInput schema / properties / quote_text_styles
        Added value: +{
        +  "description": "Styles inside the quoted text as 'start:length:STYLE' (BOLD, ITALIC, SPOILER, STRIKETHROUGH, MONOSPACE)",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / story_author
        Added value: +{
        +  "description": "Phone number of the story's author, to reply to a story",
        +  "type": "string"
        +}
      • addedInput schema / properties / story_timestamp
        Added value: +{
        +  "description": "Timestamp of the story being replied to",
        +  "type": "integer"
        +}
      • addedInput schema / properties / username
        Added value: +{
        +  "description": "Signal username (e.g. alice.42) or username link, instead of recipient",
        +  "type": "string"
        +}
      • changedInput schema / required
        Previous value: -[
        -  "recipient",
        -  "message"
        -]New value: +[
        +  "message"
        +]
    • Changedsend_note_to_self7 fields changed
      • addedInput schema / properties / no_urgent
        Added value: +{
        +  "default": false,
        +  "description": "Send without the urgent flag, so the recipient gets no push notification",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / notify_self
        Added value: +{
        +  "default": false,
        +  "description": "If you are among the recipients, deliver as a normal (notifying) message instead of a silent sync message",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / preview_description
        Added value: +{
        +  "description": "Link preview description",
        +  "type": "string"
        +}
      • addedInput schema / properties / preview_image
        Added value: +{
        +  "description": "Local image file for the link preview thumbnail",
        +  "type": "string"
        +}
      • addedInput schema / properties / preview_title
        Added value: +{
        +  "description": "Link preview title (needed for the card to render)",
        +  "type": "string"
        +}
      • addedInput schema / properties / preview_url
        Added value: +{
        +  "description": "URL for a link preview card; the same URL must also appear in the message text",
        +  "type": "string"
        +}
      • addedInput schema / properties / voice_note
        Added value: +{
        +  "default": false,
        +  "description": "Mark audio attachments as voice notes (played inline in Signal)",
        +  "type": "boolean"
        +}
    • Addedsend_story
    • Changedset_typing2 fields changed
      • addedInput schema / properties / group_id
        Added value: +{
        +  "description": "Group ID (base64) to show typing in a group",
        +  "type": "string"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "recipient"
        -]
    • Addedterminate_group
    • Changedupdate_contact6 fields changed
      • addedInput schema / properties / family_name
        Added value: +{
        +  "description": "Contact family name",
        +  "type": "string"
        +}
      • addedInput schema / properties / given_name
        Added value: +{
        +  "description": "Contact given name",
        +  "type": "string"
        +}
      • addedInput schema / properties / nick_family_name
        Added value: +{
        +  "description": "Nickname family name",
        +  "type": "string"
        +}
      • addedInput schema / properties / nick_given_name
        Added value: +{
        +  "description": "Nickname given name",
        +  "type": "string"
        +}
      • addedInput schema / properties / note
        Added value: +{
        +  "description": "Private note about the contact",
        +  "type": "string"
        +}
      • changedInput schema / required
        Previous value: -[
        -  "number",
        -  "name"
        -]New value: +[
        +  "number"
        +]
    • Changedupdate_group9 fields changed
      • addedInput schema / properties / avatar
        Added value: +{
        +  "description": "Local image file path for the new group avatar",
        +  "type": "string"
        +}
      • addedInput schema / properties / ban_members
        Added value: +{
        +  "description": "Members to ban from (re)joining the group",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / member_label
        Added value: +{
        +  "description": "YOUR OWN member label in this group (not other members')",
        +  "type": "string"
        +}
      • addedInput schema / properties / member_label_emoji
        Added value: +{
        +  "description": "Emoji for YOUR OWN member label",
        +  "type": "string"
        +}
      • addedInput schema / properties / permission_add_member
        Added value: +{
        +  "description": "Who may add new members",
        +  "enum": [
        +    "every-member",
        +    "only-admins"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / permission_edit_details
        Added value: +{
        +  "description": "Who may edit group name, description, avatar, timer",
        +  "enum": [
        +    "every-member",
        +    "only-admins"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / permission_send_messages
        Added value: +{
        +  "description": "Who may send messages ('only-admins' = announcement group)",
        +  "enum": [
        +    "every-member",
        +    "only-admins"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / reset_link
        Added value: +{
        +  "description": "Generate a new invite link, invalidating the old one",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / unban_members
        Added value: +{
        +  "description": "Members to remove from the ban list",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
    • Changedupdate_profile5 fields changed
      • addedInput schema / properties / about_emoji
        Added value: +{
        +  "description": "Emoji shown next to the about text",
        +  "type": "string"
        +}
      • addedInput schema / properties / family_name
        Added value: +{
        +  "description": "Profile family name",
        +  "type": "string"
        +}
      • addedInput schema / properties / given_name
        Added value: +{
        +  "description": "Profile given name",
        +  "type": "string"
        +}
      • addedInput schema / properties / mobilecoin_address
        Added value: +{
        +  "description": "MobileCoin address (base64)",
        +  "type": "string"
        +}
      • changedInput schema / properties / name / description
        Previous value: -"Display name to set"New value: +"Display (given) name to set; alias of given_name"
  4. 1 tool updatev1.39.0
    • Changedsearch_messages2 fields changed
      • addedInput schema / properties / since
        Added value: +{
        +  "description": "Only messages at or after this ISO datetime (e.g. 2024-01-01 or 2024-01-01T09:00:00)",
        +  "type": "string"
        +}
      • addedInput schema / properties / until
        Added value: +{
        +  "description": "Only messages strictly before this ISO datetime (exclusive; until=2024-01-02 includes all of Jan 1)",
        +  "type": "string"
        +}
  5. 3 tool updatesv1.36.0
    • Changedsend_group_message1 field changed
      • changedInput schema / properties / mentions / description
        Previous value: -"List of @mentions. Each item: {start: character offset of the mention in the message, length: character count of the mention, author: E.164 phone number of the mentioned member}. Example: message='Hello @Alice', mentions=[{start:6,length:6,author:'+1234567890'}]"New value: +"List of @mentions. Each item: {start: offset of the mention in the message (UTF-16 code units, not codepoints), length: mention length (UTF-16 code units), author: E.164 phone number of the mentioned member}. Example: message='Hello @Alice', mentions=[{start:6,length:6,author:'+1234567890'}]"
    • Changedterminate_poll2 fields changed
      • removedInput schema / properties / poll_id
        Removed value: -{
        -  "description": "Poll ID from the original poll message data",
        -  "type": "integer"
        -}
      • changedInput schema / required
        Previous value: -[
        -  "target_author",
        -  "target_timestamp",
        -  "poll_id"
        -]New value: +[
        +  "target_author",
        +  "target_timestamp"
        +]
    • Changedvote_poll2 fields changed
      • removedInput schema / properties / poll_id
        Removed value: -{
        -  "description": "Poll ID from the poll message data",
        -  "type": "integer"
        -}
      • changedInput schema / required
        Previous value: -[
        -  "target_author",
        -  "target_timestamp",
        -  "poll_id",
        -  "votes"
        -]New value: +[
        +  "target_author",
        +  "target_timestamp",
        +  "votes"
        +]
  6. 1 tool updatev1.35.0
    • Removedget_configuration
  7. 1 tool updatev1.34.1
    • Changedsend_note_to_self4 fields changed
      • addedInput schema / properties / attachments
        Added value: +{
        +  "description": "File paths to attach (e.g. a QR code or screenshot)",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedInput schema / properties / message / description
        Previous value: -"Note text to save"New value: +"Note text to save. Supports **bold**, ~~strikethrough~~, `monospace`"
      • addedInput schema / properties / quote_author
        Added value: +{
        +  "description": "Your own account number, to thread this note under a previous one",
        +  "type": "string"
        +}
      • addedInput schema / properties / quote_timestamp
        Added value: +{
        +  "description": "Timestamp of the note being followed up on (from a prior send_note_to_self result)",
        +  "type": "integer"
        +}
  8. 8 tool updatesv1.33.3
    • Addedcancel_scheduled_message
    • Addedfind_contact
    • Addedget_webhook
    • Addedlist_scheduled_messages
    • Addedreceive_direct
    • Addedrun_scheduled_messages
    • Addedschedule_message
    • Addedset_webhook
  9. 3 tool updatesv0.1.8
    • Changedsend_group_message7 fields changed
      • changedInput schema / properties / group_id / description
        Previous value: -"Group ID (get from list_groups)"New value: +"Group ID (from list_groups)"
      • changedInput schema / properties / mentions / description
        Previous value: -"List of @mentions: each item is {start, length, author} where start/length are character offsets into the message and author is a phone number"New value: +"List of @mentions. Each item: {start: character offset of the mention in the message, length: character count of the mention, author: E.164 phone number of the mentioned member}. Example: message='Hello @Alice', mentions=[{start:6,length:6,author:'+1234567890'}]"
      • addedInput schema / properties / mentions / items / properties / author / description
        Added value: +"E.164 phone number of the mentioned group member"
      • addedInput schema / properties / mentions / items / properties / length / description
        Added value: +"Length of the mention text in characters"
      • addedInput schema / properties / mentions / items / properties / start / description
        Added value: +"Character offset of the mention in the message text"
      • changedInput schema / properties / quote_author / description
        Previous value: -"Phone number of the author of the message being quoted/replied to"New value: +"Phone number (E.164) of the author of the message being quoted"
      • changedInput schema / properties / quote_timestamp / description
        Previous value: -"Timestamp of the message being quoted/replied to (from get_conversation)"New value: +"Timestamp of the quoted message (from get_conversation)"
    • Changedsend_read_receipt2 fields changed
      • changedInput schema / properties / sender / description
        Previous value: -"Phone number of the message sender"New value: +"Phone number (E.164) of the contact whose messages you are acknowledging"
      • changedInput schema / properties / timestamps / description
        Previous value: -"List of message timestamps to mark read"New value: +"Timestamps of the messages to mark as read (from get_conversation sent_at/received_at fields)"
    • Changedset_pin1 field changed
      • changedInput schema / properties / pin / description
        Previous value: -"4–20 digit PIN"New value: +"4–20 digit numeric PIN (e.g. '123456')"
  10. 23 tool updatesv0.1.2
    • Changedadmin_delete_message3 fields changed
      • changedInput schema / properties / group_id / description
        Previous value: -"Group ID"New value: +"Group ID where the message was sent (get from list_groups)"
      • changedInput schema / properties / target_author / description
        Previous value: -"Phone number of the message author"New value: +"Phone number of the user who sent the message"
      • changedInput schema / properties / target_timestamp / description
        Previous value: -"Timestamp of the message to delete"New value: +"Timestamp of the message to delete (from get_conversation)"
    • Changedblock_contact1 field changed
      • changedInput schema / properties / number / description
        Previous value: -"Phone number to block"New value: +"Phone number to block (E.164 format, e.g. +1234567890)"
    • Changedcreate_group3 fields changed
      • changedInput schema / properties / description / description
        Previous value: -"Optional group description"New value: +"Optional group description shown in group info"
      • changedInput schema / properties / members / description
        Previous value: -"Phone numbers of initial members"New value: +"Phone numbers (E.164) of initial members to invite"
      • changedInput schema / properties / name / description
        Previous value: -"Group name"New value: +"Group name visible to all members"
    • Changedcreate_poll5 fields changed
      • changedInput schema / properties / group_id / description
        Previous value: -"Group ID for a group poll"New value: +"Group ID for a group poll — provide this OR recipient"
      • changedInput schema / properties / multi_select / description
        Previous value: -"Allow multiple answer selection (default false)"New value: +"Allow voters to select multiple options (default: false = single choice only)"
      • changedInput schema / properties / options / description
        Previous value: -"List of answer options (at least 2)"New value: +"List of answer options (minimum 2 required)"
      • changedInput schema / properties / question / description
        Previous value: -"The poll question"New value: +"The poll question text"
      • changedInput schema / properties / recipient / description
        Previous value: -"Phone number for a DM poll"New value: +"Phone number for a DM poll — provide this OR group_id"
    • Changededit_message4 fields changed
      • changedInput schema / properties / group_id / description
        Previous value: -"Group ID for a group message"New value: +"Group ID for a group message edit"
      • changedInput schema / properties / message / description
        Previous value: -"New message text"New value: +"New message text to replace the original"
      • changedInput schema / properties / recipient / description
        Previous value: -"Phone number for a DM message"New value: +"Phone number for a DM message edit"
      • changedInput schema / properties / target_timestamp / description
        Previous value: -"Timestamp of the message to edit"New value: +"Timestamp of the message to edit (from get_conversation or send_message response)"
    • Changedjoin_group1 field changed
      • changedInput schema / properties / uri / description
        Previous value: -"Group invite link (https://signal.group/#...)"New value: +"Group invite link starting with https://signal.group/#"
    • Changedleave_group1 field changed
      • changedInput schema / properties / group_id / description
        Previous value: -"Group ID to leave"New value: +"Group ID to leave (get from list_groups)"
    • Changedlist_contacts1 field changed
      • changedInput schema / properties / search / description
        Previous value: -"Filter contacts by name or number (case-insensitive substring)"New value: +"Filter contacts by name or number (case-insensitive substring match)"
    • Changedpin_message4 fields changed
      • changedInput schema / properties / group_id / description
        Previous value: -"Group ID for group conversations"New value: +"Group ID for group conversations — provide this OR recipient"
      • changedInput schema / properties / recipient / description
        Previous value: -"Phone number for DM conversations"New value: +"Phone number for DM conversations — provide this OR group_id"
      • changedInput schema / properties / target_author / description
        Previous value: -"Phone number of the message author"New value: +"Phone number of the message author (E.164)"
      • changedInput schema / properties / target_timestamp / description
        Previous value: -"Timestamp of the message to pin"New value: +"Timestamp of the message to pin (from get_conversation)"
    • Changedremove_contact1 field changed
      • changedInput schema / properties / number / description
        Previous value: -"Phone number to remove"New value: +"Phone number to remove (E.164 format)"
    • Changedsend_attachment3 fields changed
      • changedInput schema / properties / caption / description
        Previous value: -"Optional caption text"New value: +"Optional caption text shown below the attachment"
      • changedInput schema / properties / paths / description
        Previous value: -"Multiple file paths to send in one message"New value: +"Multiple file paths to send as one message"
      • changedInput schema / properties / view_once / description
        Previous value: -"Send as view-once (disappears after viewing)"New value: +"Send as view-once media — recipient can only view it once before it disappears"
    • Changedsend_group_attachment3 fields changed
      • changedInput schema / properties / caption / description
        Previous value: -"Optional caption text"New value: +"Optional caption text shown below the attachment"
      • changedInput schema / properties / paths / description
        Previous value: -"Multiple file paths to send in one message"New value: +"Multiple file paths to send as one message"
      • changedInput schema / properties / view_once / description
        Previous value: -"Send as view-once (disappears after viewing)"New value: +"Send as view-once media — each recipient can only view it once"
    • Changedsend_group_message3 fields changed
      • changedInput schema / properties / mentions / description
        Previous value: -"List of @mentions: each item is {start, length, author} where author is a phone number"New value: +"List of @mentions: each item is {start, length, author} where start/length are character offsets into the message and author is a phone number"
      • changedInput schema / properties / quote_author / description
        Previous value: -"Phone number of the message being quoted/replied to"New value: +"Phone number of the author of the message being quoted/replied to"
      • changedInput schema / properties / quote_timestamp / description
        Previous value: -"Timestamp of the message being quoted/replied to"New value: +"Timestamp of the message being quoted/replied to (from get_conversation)"
    • Changedsend_group_sticker3 fields changed
      • changedInput schema / properties / group_id / description
        Previous value: -"Group ID"New value: +"Group ID (get from list_groups)"
      • changedInput schema / properties / pack_id / description
        Previous value: -"Sticker pack ID (hex string)"New value: +"Sticker pack ID (hex string from list_sticker_packs)"
      • changedInput schema / properties / sticker_id / description
        Previous value: -"Sticker ID within the pack"New value: +"Sticker ID within the pack (from list_sticker_packs)"
    • Changedsend_message2 fields changed
      • changedInput schema / properties / quote_author / description
        Previous value: -"Phone number of the message being quoted/replied to"New value: +"Phone number of the author of the message being quoted/replied to"
      • changedInput schema / properties / quote_timestamp / description
        Previous value: -"Timestamp of the message being quoted/replied to"New value: +"Timestamp of the message being quoted/replied to (from get_conversation)"
    • Changedsend_sticker2 fields changed
      • changedInput schema / properties / pack_id / description
        Previous value: -"Sticker pack ID (hex string)"New value: +"Sticker pack ID (hex string from list_sticker_packs)"
      • changedInput schema / properties / sticker_id / description
        Previous value: -"Sticker ID within the pack"New value: +"Sticker ID within the pack (from list_sticker_packs)"
    • Changedset_typing1 field changed
      • changedInput schema / properties / stop / description
        Previous value: -"True to stop typing indicator (default: False)"New value: +"Set to true to cancel an active typing indicator (default: false = start typing)"
    • Changedterminate_poll5 fields changed
      • changedInput schema / properties / group_id / description
        Previous value: -"Group ID for a group poll"New value: +"Group ID for a group poll — provide this OR recipient"
      • changedInput schema / properties / poll_id / description
        Previous value: -"Poll ID from the original poll message"New value: +"Poll ID from the original poll message data"
      • changedInput schema / properties / recipient / description
        Previous value: -"Phone number for a DM poll"New value: +"Phone number for a DM poll — provide this OR group_id"
      • changedInput schema / properties / target_author / description
        Previous value: -"Phone number of the poll creator (your own number)"New value: +"Phone number of the poll creator — must be your own number"
      • changedInput schema / properties / target_timestamp / description
        Previous value: -"Timestamp of the poll message"New value: +"Timestamp of the poll message (from get_conversation)"
    • Changedunblock_contact1 field changed
      • changedInput schema / properties / number / description
        Previous value: -"Phone number to unblock"New value: +"Phone number to unblock (E.164 format)"
    • Changedunpin_message4 fields changed
      • changedInput schema / properties / group_id / description
        Previous value: -"Group ID for group conversations"New value: +"Group ID for group conversations — provide this OR recipient"
      • changedInput schema / properties / recipient / description
        Previous value: -"Phone number for DM conversations"New value: +"Phone number for DM conversations — provide this OR group_id"
      • changedInput schema / properties / target_author / description
        Previous value: -"Phone number of the message author"New value: +"Phone number of the message author (E.164)"
      • changedInput schema / properties / target_timestamp / description
        Previous value: -"Timestamp of the pinned message"New value: +"Timestamp of the pinned message (from get_conversation)"
    • Changedupdate_account6 fields changed
      • changedInput schema / properties / delete_username / description
        Previous value: -"Delete the current username"New value: +"Delete your current Signal username"
      • changedInput schema / properties / device_name / description
        Previous value: -"Name shown on linked-device list"New value: +"Name for this device shown in linked devices list"
      • changedInput schema / properties / discoverable_by_number / description
        Previous value: -"Allow others to find you by phone number"New value: +"Allow others to find your account by phone number"
      • changedInput schema / properties / number_sharing / description
        Previous value: -"Share your number when sending messages"New value: +"Share your phone number when sending messages"
      • changedInput schema / properties / unrestricted_unidentified_sender / description
        Previous value: -"Allow sealed-sender from anyone"New value: +"Allow sealed-sender messages from anyone (not just contacts)"
      • changedInput schema / properties / username / description
        Previous value: -"Set a Signal username (without @)"New value: +"Set a Signal username (without @) as an alias for your number"
    • Changedupdate_device2 fields changed
      • changedInput schema / properties / device_id / description
        Previous value: -"Device ID from list_devices"New value: +"Device ID (get from list_devices)"
      • changedInput schema / properties / name / description
        Previous value: -"New name for the device"New value: +"New display name for the device"
    • Changedvote_poll6 fields changed
      • changedInput schema / properties / group_id / description
        Previous value: -"Group ID for a group poll"New value: +"Group ID for a group poll — provide this OR recipient"
      • changedInput schema / properties / poll_id / description
        Previous value: -"Poll ID from the original poll message"New value: +"Poll ID from the poll message data"
      • changedInput schema / properties / recipient / description
        Previous value: -"Phone number for a DM poll"New value: +"Phone number for a DM poll — provide this OR group_id"
      • changedInput schema / properties / target_author / description
        Previous value: -"Phone number of the poll creator"New value: +"Phone number of the poll creator (E.164)"
      • changedInput schema / properties / target_timestamp / description
        Previous value: -"Timestamp of the poll message"New value: +"Timestamp of the poll message (from get_conversation)"
      • changedInput schema / properties / votes / description
        Previous value: -"List of option indices to vote for (0-based)"New value: +"Option indices to vote for (0-based). Single item for single-choice polls."
  11. 72 tool updatesv0.1.0
    • First observedadd_device
    • First observedadd_sticker_pack
    • First observedadmin_delete_message
    • First observedblock_contact
    • First observedclear_local_store
    • First observedcreate_group
    • First observedcreate_poll
    • First observeddelete_group_message
    • First observeddelete_local_messages
    • First observeddelete_message
    • First observededit_message
    • First observedexport_messages
    • First observedfinish_change_number
    • First observedget_attachment
    • First observedget_avatar
    • First observedget_configuration
    • First observedget_conversation
    • First observedget_own_number
    • First observedget_profile
    • First observedget_sticker
    • First observedget_unread
    • First observedget_user_status
    • First observedimport_desktop
    • First observedjoin_group
    • First observedleave_group
    • First observedlist_accounts
    • First observedlist_attachments
    • First observedlist_contacts
    • First observedlist_conversations
    • First observedlist_devices
    • First observedlist_groups
    • First observedlist_identities
    • First observedlist_sticker_packs
    • First observedmark_as_unread
    • First observedpin_message
    • First observedprune_store
    • First observedreact_to_message
    • First observedreceive_messages
    • First observedremove_contact
    • First observedremove_device
    • First observedremove_pin
    • First observedsearch_messages
    • First observedsend_attachment
    • First observedsend_contacts_sync
    • First observedsend_group_attachment
    • First observedsend_group_message
    • First observedsend_group_sticker
    • First observedsend_message
    • First observedsend_message_request_response
    • First observedsend_note_to_self
    • First observedsend_read_receipt
    • First observedsend_sticker
    • First observedsend_sync_request
    • First observedset_expiration_timer
    • First observedset_pin
    • First observedset_typing
    • First observedstart_change_number
    • First observedstore_stats
    • First observedsubmit_rate_limit_challenge
    • First observedsync_desktop
    • First observedterminate_poll
    • First observedtrust_identity
    • First observedunblock_contact
    • First observedunpin_message
    • First observedupdate_account
    • First observedupdate_configuration
    • First observedupdate_contact
    • First observedupdate_device
    • First observedupdate_group
    • First observedupdate_profile
    • First observedupload_sticker_pack
    • First observedvote_poll

TDQS

A4.1/5.0

Scored across 81 tools

Disambiguation4/5

Despite 81 tools, descriptions carefully carve out boundaries (e.g. send_message vs send_group_message vs send_attachment vs send_note_to_self, and the many DM/group pairs like delete_message vs delete_group_message). A few near-duplicates exist (get_unread vs receive_messages vs receive_direct; get_profile vs find_contact vs get_user_status) but cross-references make the intent clear.

Naming Consistency4/5

Strong verb_noun snake_case throughout (send_message, list_contacts, update_group, remove_device, set_typing). Minor deviations like send_message_request_response and the receive_* family are still readable and consistently styled.

Tool Count1/5

81 tools is far beyond what an agent can navigate comfortably; many are thin variants (send_sticker vs send_group_sticker, delete_message vs delete_group_message, multiple receive_* and store-cleanup tools). This is an extreme surface for a single messaging server.

Completeness5/5

Coverage is exhaustive: messaging, groups, contacts, devices, stickers, polls, stories, reactions, pins, scheduling, identity/trust, account settings, webhooks, and local store management. CRUD and lifecycle operations are present across almost every domain.

Maintenance

ActivityMaintained
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    MCP server for Signal via signal-cli that enables sending and receiving messages, managing contacts and groups, and reacting over stdio.
    8 npm
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server for a local-first messaging workspace that integrates Google Messages, WhatsApp, and Signal. It enables reading, sending, searching messages, and managing conversations through MCP tools.
    63
    -