Skip to main content

Tools

Signal MCP exposes the following MCP tools:

send

Send a message to the channel operator's phone. No phone number needed — this uses the --operator configured at startup.

ParameterTypeRequiredDescription
messagestrYesThe message to send
send(message="Hey, the deploy is done!")

send_message_to_user

Send a direct message to a specific Signal user.

ParameterTypeRequiredDescription
messagestrYesThe message to send
user_idstrYesRecipient phone number (e.g. +15551234567)
send_message_to_user(message="Hello!", user_id="+15551234567")

send_message_to_group

Send a message to a Signal group. The group_id can be the group's internal ID or its display name.

ParameterTypeRequiredDescription
messagestrYesThe message to send
group_idstrYesGroup internal ID or display name
send_message_to_group(message="Team update", group_id="#dev-team")

send_reaction_to_user

React to a user's message with an emoji.

ParameterTypeRequiredDescription
emojistrYesThe emoji to react with
user_idstrYesRecipient phone number
target_authorstrYesAuthor of the message being reacted to
target_timestampintYesTimestamp of the target message
removeboolNoSet True to remove a reaction (default: False)
send_reaction_to_user(
emoji="👍",
user_id="+15551234567",
target_author="+15551234567",
target_timestamp=1744185565466,
)

send_reaction_to_group

React to a message in a group with an emoji.

ParameterTypeRequiredDescription
emojistrYesThe emoji to react with
group_idstrYesGroup internal ID or display name
target_authorstrYesAuthor of the message being reacted to
target_timestampintYesTimestamp of the target message
removeboolNoSet True to remove a reaction (default: False)

receive_message

Wait for and receive the next actionable message (text or reaction) within a timeout. Messages that arrived while the daemon was streaming are queued, so back-to-back calls won't drop anything.

ParameterTypeRequiredDescription
timeoutfloatNoSeconds to wait (default: 60)

Returns a MessageResponse with either:

  • Text message: message, sender_id, sender_name, group_id, timestamp
  • Reaction: reaction (emoji, target_author, target_timestamp, is_remove)
  • Timeout: empty response (all fields None)
result = await receive_message(timeout=30.0)
if result.message:
print(f"Got: {result.message} from {result.sender_id}")
elif result.reaction:
print(f"Got reaction: {result.reaction.emoji}")

mark_read

Mark a received message as read in Signal. In channel mode this happens automatically when a message is forwarded. In normal (polling) mode, call this after receive_message to send a read receipt.

ParameterTypeRequiredDescription
senderstrYesSender phone number (from sender_id in the received message)
target_timestampintYesMessage timestamp (from timestamp in the received message)
result = await mark_read(
sender="+15551234567",
target_timestamp=1744185565466,
)