Skip to main content
Glama
mcp-signal

mcp-signal

by Sealjay

mcp-signal

Python uv MCP License: MIT GitHub issues GitHub stars Sealjay/mcp-signal MCP server

A local MCP server for Signal. It reads and searches your Signal Desktop history via signal-export and sends messages via signal-cli. Everything runs on your machine over stdio, with an optional HTTP mode.

Mixed backend. Reads come from the local Signal Desktop database. Sends need signal-cli installed and linked separately; without it, read and search still work.

Setup

Prerequisites: Python 3.12+, uv, Signal Desktop with local history, and (for sends) signal-cli.

git clone https://github.com/Sealjay/mcp-signal.git
cd mcp-signal
uv sync
brew install signal-cli   # optional, sends only

Tested with signal-cli 0.14.8; 0.14.9 changes nothing this server uses.

Configure sends

Put machine-local config in .env.local at the repo root (gitignored):

echo 'SIGNAL_ACCOUNT="+441234567890"' > .env.local

Variable

Purpose

SIGNAL_ACCOUNT

Linked signal-cli account used for sends

SIGNAL_CLI_PATH

Override the signal-cli binary path

SIGNAL_DATA_DIR

Override the Signal Desktop data directory

SIGNAL_DB_PASSWORD / SIGNAL_DB_KEY

Password or raw key for an encrypted desktop DB

SIGNAL_JSONRPC_TIMEOUT_SECONDS

signal-cli JSON-RPC timeout. Default 30, max 300

MCP_AUTH_TOKEN

Bearer token for HTTP mode (all routes except /health). Unset means no auth

MCP_LISTEN_ADDR

host:port for HTTP mode; setting it enables HTTP mode. Default 0.0.0.0:8765

Shell variables override .env.local. .env.local only loads SIGNAL_* keys, so set MCP_* in the shell.

signal-cli link -n "signal-mcp"   # scan the QR: Signal app > Settings > Linked Devices
signal-cli listAccounts           # should match SIGNAL_ACCOUNT
uv run signal-mcp smoke

signal-cli keeps its linked-device state in its own data directory (usually ~/.local/share/signal-cli/data), outside this repo.

HTTP mode (optional)

uv run signal-mcp serve --http --listen-addr 0.0.0.0:8765

Streamable HTTP at /mcp. It is stateless (no Mcp-Session-Id, and GET /mcp returns 405 because there is no standalone SSE stream) and serves MCP 2026-07-28 as well as older revisions.

OpenAI Secure MCP Tunnel (optional)

.tunnel-client/ runs the stdio server behind OpenAI's outbound tunnel client for ChatGPT. See .tunnel-client/README.md. Copy .env.example to .env.local (gitignored) and keep the tunnel key as a 1Password op:// reference; never commit real IDs or keys.

Related MCP server: Signal MCP

MCP client configuration

Every client launches the server over stdio with the same block. Use an absolute repo path.

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

Client

Where

Claude Code

claude mcp add --transport stdio signal --scope user -- uv run --directory /absolute/path/to/mcp-signal signal-mcp serve, or the block above in .mcp.json

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json

Cursor

~/.cursor/mcp.json

Restart the client afterwards. If a GUI app reports spawn uv ENOENT, set command to the absolute path from which uv (Homebrew: /opt/homebrew/bin/uv).

Tools

Tool

Purpose

list_chats

List direct and group chats from Signal Desktop

read_messages

Read messages from a specific chat

search_messages

Search messages within one chat or across all chats

list_groups

List groups from signal-cli, including group IDs

chat_activity

Rank chats by recent activity, with last-message/last-reply dates and unanswered-inbound counts

decrypt_attachment

Decrypt a locally stored attachment and return the decrypted file's path

send_message

Send text to a phone number, group ID or exact chat name. chat_name resolves to the contact's service ID when their number is hidden

get_status

Show desktop DB / signal-cli / account readiness

pairing_status

Report signal-cli link state and surface the live link QR

Prompts: summarise_chat and discover_topics.

Architecture

Component

Description

MCP server

Python/FastMCP 4, stdio or stateless streamable HTTP

Read path

signal-export against the local Signal Desktop database

Send path

signal-cli -a ACCOUNT jsonRpc, launched on demand

State

No cache; reads Signal Desktop data directly

Privacy and limitations

  • No cloud relay; data stays on your machine. HTTP mode is opt-in, and bearer auth applies only when MCP_AUTH_TOKEN is set (the default bind is 0.0.0.0).

  • Prompt injection: this server has the lethal trifecta. A malicious incoming message could try to make an agent exfiltrate others, so review outbound actions before approving them.

  • Text-only sends; no real-time notifications; one account per instance.

  • Group sends need signal-cli; the desktop DB alone cannot address groups safely.

  • Read metadata comes from Signal Desktop, not signal-cli. Voice notes are flagged is_voice_note from Desktop's attachment flag.

Report vulnerabilities via SECURITY.md.

Troubleshooting

  • signal-cli not found: put it on PATH or set SIGNAL_CLI_PATH.

  • Reads work, sends fail: signal-cli is not linked or SIGNAL_ACCOUNT is unset. Check signal-cli listAccounts.

  • [403] Authorization failed: the linked device was removed or expired. Re-link with signal-cli link -n "signal-mcp".

  • signal-cli link hangs: don't pass -a/--account to link.

  • No messages returned: confirm Signal Desktop is installed and has history.

Development

uv sync
uv run ruff check .
uv run pytest
uv run signal-mcp smoke

CI runs the same on every pull request. See CLAUDE.md for structure and constraints.

Licence

MIT. See LICENSE.

Available Tools

9 tools
chat_activityChat ActivityA
Read-onlyIdempotent

List Signal chats ranked by recent activity, showing last message date, last reply date, and count of unanswered inbound messages.

Read-only with no side effects. Use this to identify chats that need a response. Use list_chats instead for a general chat directory with message previews.

NameRequiredDescriptionDefault
limitNoMaximum number of chats to return, between 1 and 200. Defaults to 50.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already cover safety (readOnlyHint, idempotentHint, destructiveHint=false), so the repeated "Read-only with no side effects" adds little. The description does add meaningful behavior by explaining the ranking and the computed fields (last message date, last reply date, unanswered inbound count), though it leaves sorting tie behavior and pagination unstated.

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 short and front-loaded: it states the primary purpose first, then the safety profile and usage guidance. Every sentence contributes to selection or interpretation.

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 rich annotations, a fully described parameter, and an output schema present, the description need not explain return values in detail. It still provides enough purpose, usage, and behavioral context for an agent to call the tool 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 limit parameter is already fully documented in the schema. The description does not add syntax or filtering semantics for limit, so the baseline of 3 is appropriate.

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

Purpose5/5

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

The description gives a specific verb and resource ("List Signal chats") and adds the ranking criterion (recent activity) plus the fields surfaced. It explicitly distinguishes itself from list_chats, so an agent can select 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?

It states the intended use case ("identify chats that need a response") and names the alternative (list_chats) with the condition that selects it (general chat directory with message previews). This is explicit when-to-use guidance.

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

decrypt_attachmentDecrypt AttachmentA

Decrypt a locally stored Signal attachment and return the path to the decrypted file.

The encrypted_path and local_key values come from attachment metadata in read_messages or search_messages results. Read-only on Signal data; writes a decrypted copy to a temporary directory (the temp file is not auto-cleaned). Returns the absolute path to the decrypted file as a string on success, or a string starting with 'Error:' on failure (missing file, wrong key length, or HMAC mismatch). Use this after reading messages that contain attachments.

NameRequiredDescriptionDefault
local_keyYesBase64-encoded 64-byte key (32-byte AES-CBC + 32-byte HMAC-SHA256), from the 'local_key' field of attachment metadata.
encrypted_pathYesAbsolute filesystem path to the encrypted attachment file, as returned in the 'encrypted_path' field of message attachment metadata.

Output Schema

NameRequiredDescription
resultYes

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: it discloses that it is read-only on Signal data but writes a decrypted copy to a temp directory that is not auto-cleaned, and enumerates failure modes (missing file, wrong key length, HMAC mismatch) with the 'Error:' prefix convention. This is exactly the side-effect and auth/state context an agent needs before calling.

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 clause and each sentence carries operational content. The return-value explanation is somewhat redundant given an output schema exists, which slightly blunts conciseness.

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?

Covers source of inputs, side effects, cleanup caveats, and error surface, which is everything needed for a two-parameter cryptographic tool with an output schema and annotations already present.

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 ('attachment metadata in read_messages or search_messages results') that tells the agent where to obtain the values. It does not restate format details, which the schema already covers well.

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 ('Decrypt a locally stored Signal attachment') plus the outcome ('return the path to the decrypted file'). This is clearly distinct from the reading/searching siblings that merely surface the metadata this tool consumes.

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 the agent: values 'come from attachment metadata in read_messages or search_messages results' and 'Use this after reading messages that contain attachments.' It gives clear positive conditions but no explicit when-not-to-use or alternate tool.

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

get_statusGet StatusA
Read-onlyIdempotent

Check whether the Signal MCP server can read local messages and send outbound messages.

Returns boolean fields: source_dir_exists, signal_cli_available, signal_account_configured, read_available, send_available. Read-only with no side effects. Call this before read or send operations to verify configuration; call pairing_status instead to check first-run device-linking state.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

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 'read-only with no side effects' adds little beyond structured data. However, the description does add real value by tying the check to a pre-flight workflow and by naming the configuration conditions (source dir, CLI availability, account configuration) that gate later operations.

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 check, then the return shape, then the routing guidance — a sensible order with no filler. Slight redundancy in listing the five boolean field names when an output schema already exists, but it is compact enough not to be a real cost.

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, read-only status probe with full annotation coverage and an output schema, the description covers purpose, preconditions, return semantics and the sibling alternative. 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.

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. Baseline 4 applies; the description correctly spends no space on 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 names a specific check ('whether the Signal MCP server can read local messages and send outbound messages') rather than restating the name, and it enumerates the exact boolean fields returned. It is clearly distinguishable from siblings like pairing_status and read_messages.

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

Usage Guidelines5/5

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

Explicit when-to-use ('call this before read or send operations to verify configuration') and an explicit alternative with its condition ('call pairing_status instead to check first-run device-linking state'). An agent has no inference left to make about tool selection.

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

list_chatsList ChatsA
Read-onlyIdempotent

List direct and group Signal chats from the local desktop database, sorted by most recent message.

Each result includes name, phone number, message count, and a preview of the last message. Read-only with no side effects. Use this to discover exact chat names before calling read_messages or search_messages. Use list_groups instead when you need group_id values for send_message.

NameRequiredDescriptionDefault
limitNoMaximum number of chats to return, between 1 and 200. Defaults to 50.
queryNoCase-insensitive substring to filter by chat name or phone number. Empty string returns all chats.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/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 'Read-only with no side effects' is largely redundant. The description does add non-annotation context: the data source (local desktop database) and the result ordering (most recent message first), which affects how an agent interprets results. No auth or pagination caveats, but nothing contradicts annotations.

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

Conciseness4/5

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

Front-loaded with the core action and scope, followed by return contents and sibling routing. Efficient overall, though 'Read-only with no side effects' duplicates the annotation block and doesn't add signal.

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?

Output schema exists so return values needn't be described, annotations cover the safety profile, and schema fully documents both parameters. The description contributes the remaining needs: data source, sort order, and sibling routing. 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 coverage is 100% with defaults and ranges documented for both limit and query, so the schema already does the work. The description mentions no parameter behavior at all (e.g., how limit interacts with sorting, or whether query matches phone numbers), so the baseline of 3 is right.

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 direct and group Signal chats from the local desktop database') with scope qualifiers: local database, sorted by most recent message. Clearly separable from list_groups, which it names as a different scope.

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 ('discover exact chat names before calling read_messages or search_messages') and an explicit when-to-use-alternative ('Use list_groups instead when you need group_id values for send_message'). This routes the agent between siblings with no inference required.

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

list_groupsList GroupsA
Read-onlyIdempotent

List Signal groups with group_id, name, description, members, and admin lists, sorted alphabetically.

Read-only with no side effects. Queries signal-cli when available; falls back to the local desktop database (without group_id). Use this to obtain group_id values needed by send_message. Use list_chats instead for a combined view of both direct and group chats.

NameRequiredDescriptionDefault
limitNoMaximum number of groups to return, between 1 and 200. Defaults to 50.
queryNoCase-insensitive substring to filter group names. Empty string returns all groups.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

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

Adds behavior beyond the annotations: a dual data source with a degraded fallback ("falls back to the local desktop database (without group_id)"), which is correctness-critical since the group_id may be absent. The safety profile is only restated from annotations ("Read-only with no side effects") and there is no mention of latency, rate limits, or whether the fallback is surfaced in the result, keeping it 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?

Front-loaded with the resource and return fields, then source caveat, then routing guidance — a sensible information hierarchy with no filler. The "Read-only with no side effects" sentence largely duplicates the annotations and could be dropped.

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?

An output schema exists, so return values need no explanation, yet the description still names the key fields and their ordering. Combined with the fallback caveat and the sibling routing note, 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%, with both limit (range 1-200, default 50) and query (case-insensitive substring, empty returns all) fully documented in the schema. The description says nothing extra about filtering or pagination, so it meets but does not exceed the baseline for a fully documented 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 Signal groups") and enumerates the returned fields (group_id, name, description, members, admin lists) plus the sort order. It also explicitly distinguishes itself from list_chats, so an agent can pick 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?

Gives a concrete downstream use ("obtain group_id values needed by send_message") and names the alternative with the condition that selects it ("Use list_chats instead for a combined view of both direct and group chats"). Both when-to-use and when-to-use-something-else are covered.

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

pairing_statusPairing StatusA

Report the Signal device-linking setup state for first-run pairing, so a client can surface the live link QR.

Returns a setup_state envelope: state 'ready' with the linked account once signal-cli is linked; 'awaiting_qr' with a 'qr_payload' sgnl://linkdevice URI to scan in Signal (Settings → Linked devices → Link new device) while a link is in progress (no payload yet on the first call, until the URI is captured); or 'error' when signal-cli is unavailable. Read-only from the caller's view, but the first call on an unlinked device starts a background signal-cli link process as a side effect. Poll this to drive a pairing UI; call get_status instead to check read/send availability once linked.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

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

Annotations declare readOnlyHint=false and idempotentHint=false but never explain why; the description supplies the reason — the first call on an unlinked device spawns a background signal-cli link process as a side effect. It also details the three state outcomes and the expected empty qr_payload on the first call, which no structured field conveys.

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 the return states, then the side-effect caveat, then the sibling routing — a sensible information order. The line-wrapped prose and heavier detail on the envelope 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?

Covers the three possible states, the expected empty first-call payload, the background process side effect, and the handoff to get_status — everything an agent needs to call and interpret 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?

Zero parameters, so the baseline is 4. The description compensates by documenting the return envelope (ready/awaiting_qr/error, qr_payload) even though an output schema 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 ('Report the Signal device-linking setup state') plus the caller-facing goal (surface the live link QR). It explicitly routes the agent away from get_status once linked, so it is distinguishable from siblings 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 ('Poll this to drive a pairing UI'), when-not ('call get_status instead to check read/send availability once linked'), and the polling cadence implied by the awaiting_qr flow. Nothing is left 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.

read_messagesRead MessagesA
Read-onlyIdempotent

Read messages from a single Signal chat, returned newest-first.

Each message includes sender, date, body text, reactions, and attachment metadata. Read-only with no side effects. Requires an exact chat name from list_chats. Use search_messages instead to find messages by keyword across chats.

NameRequiredDescriptionDefault
afterNoISO 8601 datetime; only return messages sent after this time, e.g. '2025-01-15T00:00:00'.
limitNoMaximum number of messages to return, between 1 and 200. Defaults to 20.
beforeNoISO 8601 datetime; only return messages sent before this time, e.g. '2025-02-01T00:00:00'.
offsetNoNumber of messages to skip from the most recent, for pagination (0-10000). Defaults to 0.
chat_nameYesExact chat name as returned by list_chats (case-sensitive).

Output Schema

NameRequiredDescription
resultYes

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 'read-only with no side effects' sentence is largely redundant, but it does not contradict them. The description adds real behavioral value beyond annotations: messages come back newest-first, and each item carries sender, date, body, reactions and attachment metadata. It omits pagination/limit behavior, which keeps it from a 5.

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

Conciseness5/5

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

Four short sentences, front-loaded with what the tool returns and in what order, then contents, safety, prerequisite, and alternative. 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?

Output schema exists, schema coverage is complete, and annotations cover the safety profile, so the description only needs orientation — which it provides (ordering, contents, prerequisite, alternative). Slight gap: no mention that results are paginated via limit/offset, though the schema covers 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 description coverage is 100%, so after/before/limit/offset/chat_name are already fully documented in the schema. The description only reinforces the case-sensitivity prerequisite for chat_name and adds nothing about the time-window or pagination parameters, 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 and resource (read messages from a single Signal chat) plus an important scope detail: returned newest-first. It explicitly distinguishes itself from both list_chats (name source) and search_messages (keyword search across chats), so an agent can pick it without reading 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 prerequisite (exact chat name from list_chats) and a named alternative with the condition that selects it ('Use search_messages instead to find messages by keyword across chats'). Both when-to-use and when-not-to-use are covered.

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

search_messagesSearch MessagesA
Read-onlyIdempotent

Search Signal message bodies for a keyword, within one chat or across all chats, returned newest-first.

Each result includes sender, date, chat name, body text, reactions, and attachment metadata. Read-only with no side effects. Use this to find messages by content. Use read_messages instead to browse a specific chat chronologically.

NameRequiredDescriptionDefault
limitNoMaximum number of matching messages to return, between 1 and 200. Defaults to 20.
queryYesCase-insensitive substring to search for within message bodies.
chat_nameNoExact chat name to restrict the search to a single chat. Omit to search across all chats.

Output Schema

NameRequiredDescription
resultYes

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 non-destructive, so the 'Read-only with no side effects' sentence adds nothing new. However the description does add genuinely non-annotated behavior: newest-first ordering, the per-chat vs. global scope, and the exact result fields (sender, date, chat name, body, reactions, attachment metadata). Pagination behavior is still unstated, keeping it below 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 and scope, then results, then routing. Nearly every sentence earns its place, though 'Read-only with no side effects' duplicates the annotations and could be dropped.

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?

An output schema exists, so return values need not be explained, yet the description still summarizes them usefully. Scope, ordering, and sibling routing are all present; nothing an agent needs to invoke the tool 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 query, limit, and chat_name are fully documented in the schema, including case-insensitivity and the 1-200 range. The description only restates the chat-vs-all scope and adds no format or syntax detail beyond the schema; baseline 3 applies.

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

Purpose5/5

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

States a specific verb and resource ('Search Signal message bodies'), the searchable scope (one chat or all chats), and the ordering (newest-first). It explicitly contrasts itself with read_messages, so an agent can distinguish 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?

Gives explicit selection criteria: 'Use this to find messages by content. Use read_messages instead to browse a specific chat chronologically.' The alternative and the condition that selects it are both named.

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

send_messageSend MessageA

Send a text message via Signal to a direct recipient or group.

This is a write operation that delivers a real message through signal-cli. Sends are not reversible from this server — Signal supports user-initiated message deletion only via the official clients. Exactly one of phone_number, group_id, or chat_name must be supplied; providing zero or more than one raises an error. Rate-limited to 1 message per recipient per second and 10 messages per 60-second window globally. Requires signal-cli and SIGNAL_ACCOUNT to be configured — call get_status first to verify send_available is true. Returns target_type, target identifier, and timestamp on success.

NameRequiredDescriptionDefault
messageYesThe text message content to send.
group_idNoTarget group ID as returned by list_groups. Mutually exclusive with phone_number and chat_name.
chat_nameNoExact chat name from list_chats; auto-resolves to the matching phone_number, service ID or group_id. Mutually exclusive with the other two recipient fields.
phone_numberNoRecipient phone number in E.164 format (e.g. '+441234567890'). Mutually exclusive with group_id and chat_name.

Output Schema

NameRequiredDescription

No output parameters

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, openWorldHint=true, idempotentHint=false, destructiveHint=false). It discloses irreversibility ('Sends are not reversible from this server'), that deletion is only via official clients, concrete rate limits (1 per recipient per second, 10 per 60s globally), the external dependency on signal-cli/SIGNAL_ACCOUNT, and the success return 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-loads the one-line purpose, then layers constraints, rate limits, prerequisites, and return info in short discrete sentences. It is longer than minimal but every sentence carries a distinct operational fact; only minor trimming 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?

An output schema exists, yet the description still name-checks the success payload (target_type, target identifier, timestamp). Combined with constraints, rate limits, and prerequisites, 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 adds the crucial exactly-one-recipient rule and states that zero or more than one raises an error — stricter information than the schema's 'mutually exclusive' notes and not derivable from the required list (only message is required).

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 text message via Signal) plus the two target types (direct recipient or group). This clearly separates it from read_messages, search_messages, and chat_activity among the siblings.

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

Usage Guidelines4/5

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

Gives an explicit prerequisite: signal-cli and SIGNAL_ACCOUNT must be configured, and the agent should call get_status first to verify send_available is true. It does not explicitly name alternative send paths or exclusion cases, but the precondition guidance is concrete and actionable.

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. 7 tool updatesv0.2.1
    • Changedchat_activity1 field changed
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of chats to return, between 1 and 200."New value: +"Maximum number of chats to return, between 1 and 200. Defaults to 50."
    • Changedlist_chats1 field changed
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of chats to return, between 1 and 200."New value: +"Maximum number of chats to return, between 1 and 200. Defaults to 50."
    • Changedlist_groups1 field changed
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of groups to return, between 1 and 200."New value: +"Maximum number of groups to return, between 1 and 200. Defaults to 50."
    • Addedpairing_status
    • Changedread_messages2 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of messages to return, between 1 and 200."New value: +"Maximum number of messages to return, between 1 and 200. Defaults to 20."
      • changedInput schema / properties / offset / description
        Previous value: -"Number of messages to skip from the most recent, for pagination (0-10000)."New value: +"Number of messages to skip from the most recent, for pagination (0-10000). Defaults to 0."
    • Changedsearch_messages1 field changed
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of matching messages to return, between 1 and 200."New value: +"Maximum number of matching messages to return, between 1 and 200. Defaults to 20."
    • Changedsend_message1 field changed
      • changedInput schema / properties / chat_name / description
        Previous value: -"Exact chat name from list_chats; auto-resolves to the matching phone_number or group_id. Mutually exclusive with the other two recipient fields."New value: +"Exact chat name from list_chats; auto-resolves to the matching phone_number, service ID or group_id. Mutually exclusive with the other two recipient fields."
  2. 16 tool updatesv0.1.3
    • Addedchat_activity
    • Addeddecrypt_attachment
    • Changedlist_chats2 fields changed
      • addedInput schema / properties / limit / description
        Added value: +"Maximum number of chats to return, between 1 and 200."
      • addedInput schema / properties / query / description
        Added value: +"Case-insensitive substring to filter by chat name or phone number. Empty string returns all chats."
    • Changedlist_groups2 fields changed
      • addedInput schema / properties / limit / description
        Added value: +"Maximum number of groups to return, between 1 and 200."
      • addedInput schema / properties / query / description
        Added value: +"Case-insensitive substring to filter group names. Empty string returns all groups."
    • Changedread_messages5 fields changed
      • addedInput schema / properties / after / description
        Added value: +"ISO 8601 datetime; only return messages sent after this time, e.g. '2025-01-15T00:00:00'."
      • addedInput schema / properties / before / description
        Added value: +"ISO 8601 datetime; only return messages sent before this time, e.g. '2025-02-01T00:00:00'."
      • addedInput schema / properties / chat_name / description
        Added value: +"Exact chat name as returned by list_chats (case-sensitive)."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum number of messages to return, between 1 and 200."
      • addedInput schema / properties / offset / description
        Added value: +"Number of messages to skip from the most recent, for pagination (0-10000)."
    • Changedsearch_messages3 fields changed
      • addedInput schema / properties / chat_name / description
        Added value: +"Exact chat name to restrict the search to a single chat. Omit to search across all chats."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum number of matching messages to return, between 1 and 200."
      • addedInput schema / properties / query / description
        Added value: +"Case-insensitive substring to search for within message bodies."
    • Changedsend_message4 fields changed
      • addedInput schema / properties / chat_name / description
        Added value: +"Exact chat name from list_chats; auto-resolves to the matching phone_number or group_id. Mutually exclusive with the other two recipient fields."
      • addedInput schema / properties / group_id / description
        Added value: +"Target group ID as returned by list_groups. Mutually exclusive with phone_number and chat_name."
      • addedInput schema / properties / message / description
        Added value: +"The text message content to send."
      • addedInput schema / properties / phone_number / description
        Added value: +"Recipient phone number in E.164 format (e.g. '+441234567890'). Mutually exclusive with group_id and chat_name."
    • Removedsignal_chat_activity
    • Removedsignal_get_chat_messages
    • Removedsignal_get_status
    • Removedsignal_list_chats
    • Removedsignal_list_groups
    • Removedsignal_read_messages
    • Removedsignal_search_chat
    • Removedsignal_search_messages
    • Removedsignal_send_message
  3. 15 tool updatesv0.1.2
    • First observedget_status
    • First observedlist_chats
    • First observedlist_groups
    • First observedread_messages
    • First observedsearch_messages
    • First observedsend_message
    • First observedsignal_chat_activity
    • First observedsignal_get_chat_messages
    • First observedsignal_get_status
    • First observedsignal_list_chats
    • First observedsignal_list_groups
    • First observedsignal_read_messages
    • First observedsignal_search_chat
    • First observedsignal_search_messages
    • First observedsignal_send_message

TDQS

A4.5/5.0

Scored across 9 tools

Disambiguation5/5

Each tool has a narrow, distinct purpose, and descriptions explicitly route the agent elsewhere when overlap exists (e.g. chat_activity vs list_chats, read_messages vs search_messages, get_status vs pairing_status). The only natural overlap is list_chats also covering groups, but list_groups is clearly framed as the source of group_id values. An agent should never misselect here.

Naming Consistency4/5

Most tools follow a clean verb_noun pattern (list_chats, read_messages, search_messages, send_message, decrypt_attachment). Two names deviate by dropping the verb (chat_activity, pairing_status), where get_ is implied by analogy with get_status. Minor and still readable.

Tool Count5/5

Nine tools is well-scoped for a Signal read/send bridge: discovery, reading, search, activity triage, attachment decryption, diagnostic/pairing state, and one write path. No obviously redundant or filler tools.

Completeness4/5

Core lifecycle is covered: discover chats/groups, read and search messages, decrypt attachments, check configuration/pairing, and send text messages. Gaps remain on the write side — no sending attachments, no group creation/management, no message deletion — though these are reasonable scope limits rather than dead ends for the stated read-focused purpose.

Maintenance

ActivityMaintained
ResponsivenessSlow

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    MCP server for Signal via signal-cli that enables sending and receiving messages, managing contacts and groups, and reacting over stdio.
    15 npm
    -
  • A
    license
    Not graded
    quality
    B
    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.
    71
    -