Signal (PyPI) MCP Server

signal-mcp PyPI v1.36.0

Published by an unidentified publisher — no publish provenance and no public repository, so the publisher could not be verified and the source cannot be independently located.

Complete Signal MCP server and CLI via signal-cli

Trust grade
B
83/100
Last scanned get badge →
Trust
B · 83/100
Adoption risk for you: the threat score, then adjusted down for blast radius, publisher verification and how much the scan could see. Deterministic; every point is auditable.
Capability
High
Blast radius if it went rogue — what the server’s tools could reach. Independent of trust.
Coverage
Source
How much the scan could actually inspect. Shallow coverage is stated, never hidden.
Share this Trust Score
𝕏 Share LinkedIn Reddit
B Why this grade threat 91 − adoption risk = 83/100

The grade answers one question — how safe is this server for you to adopt — so it is computed in two auditable stages. Nothing below is an opinion or an LLM's guess; every line is a real term the deterministic engine applied, and the same input always yields the same number.

1. Threat score — 100 − 9.5 = 91. What the published surface and source actually contain:

PointsWhat was foundCategory
−9.5 Description names a credential store the tool cannot reach ×2 MTC-INJ-SCHEMA-1 injection

2. Client adoption risk — 91 − 8 = 83. Three small, subtract-only factors that reflect your risk in adopting it — a clean scan proves less on a powerful, unverified or barely-inspectable package, so the grade says so plainly:

PointsAdoption-risk factor
−6 capability blast radius (high) — client exposure if the model is manipulated
−2 publisher verification (unlinked) — no provenance/repo link, but the shipped source was fully read

Capability observations and info notes are shown under Findings but never scored. Open any row's finding below for the file, line and evidence behind a deduction.

Findings 7

high Shell/command execution in server code (src/signal_mcp/cli.py)MTC-SRC-002

In the server's implementation (`src/signal_mcp/cli.py:483`): Spawning a shell/process is command-execution capability; with unsanitized tool input it is command injection / RCE. This is read from the code itself — not from the tool description — so a poisoned server cannot hide it behind honest-looking metadata.

Evidence: ragma: no cover subprocess.run([ "signal-cli", "-u", account, "daemon", f"--http", f"loc

Fix: Review this call path: confirm it never receives unsanitized tool input, constrain it, or remove it. Treat a server whose code reaches these sinks as high-capability regardless of what its tools claim.

Location: server src/signal_mcp/cli.py

high Shell/command execution in server code (src/signal_mcp/client.py)MTC-SRC-002

In the server's implementation (`src/signal_mcp/client.py:185`): Spawning a shell/process is command-execution capability; with unsanitized tool input it is command injection / RCE. This is read from the code itself — not from the tool description — so a poisoned server cannot hide it behind honest-looking metadata.

Evidence: .5) proc = subprocess.Popen( [ "signal-cli", "-u", self.account,

Fix: Review this call path: confirm it never receives unsanitized tool input, constrain it, or remove it. Treat a server whose code reaches these sinks as high-capability regardless of what its tools claim.

Location: server src/signal_mcp/client.py

high Shell/command execution in server code (src/signal_mcp/config.py)MTC-SRC-002

In the server's implementation (`src/signal_mcp/config.py:46`): Spawning a shell/process is command-execution capability; with unsanitized tool input it is command injection / RCE. This is read from the code itself — not from the tool description — so a poisoned server cannot hide it behind honest-looking metadata.

Evidence: JVM start) result = subprocess.run( ["signal-cli", "listAccounts"], capture_output=True, tex

Fix: Review this call path: confirm it never receives unsanitized tool input, constrain it, or remove it. Treat a server whose code reaches these sinks as high-capability regardless of what its tools claim.

Location: server src/signal_mcp/config.py

high Shell/command execution in server code (src/signal_mcp/desktop.py)MTC-SRC-002

In the server's implementation (`src/signal_mcp/desktop.py:67`): Spawning a shell/process is command-execution capability; with unsanitized tool input it is command injection / RCE. This is read from the code itself — not from the tool description — so a poisoned server cannot hide it behind honest-looking metadata.

Evidence: ): result = subprocess.run( ["security", "find-generic-password", "-s", service, "-w"],

Fix: Review this call path: confirm it never receives unsanitized tool input, constrain it, or remove it. Treat a server whose code reaches these sinks as high-capability regardless of what its tools claim.

Location: server src/signal_mcp/desktop.py

medium Description names a credential store the tool cannot reachMTC-INJ-SCHEMA-1

Tool "get_unread" describes a credential store (SSH keys, cloud credentials, a keychain or an equivalent) that nothing in its input schema can address. A tool's interface is the honest statement of what it touches; prose that reaches past it is addressed to the model, not to a reader.

Evidence: Keychain

Fix: Remove the reference, or expose the target as an explicit, validated parameter so the client can see and consent to what the tool reads.

Location: tool get_unread · description

medium Description names a credential store the tool cannot reachMTC-INJ-SCHEMA-1

Tool "import_desktop" describes a credential store (SSH keys, cloud credentials, a keychain or an equivalent) that nothing in its input schema can address. A tool's interface is the honest statement of what it touches; prose that reaches past it is addressed to the model, not to a reader.

Evidence: Keychain

Fix: Remove the reference, or expose the target as an explicit, validated parameter so the client can see and consent to what the tool reads.

Location: tool import_desktop · description

medium Unconstrained URL/host parameter "url" on "set_webhook"MTC-CAP-007

Tool "set_webhook" takes a URL/host parameter "url" with no allowlist/pattern. An outbound-request tool with an unbounded destination enables SSRF and cloud-metadata access (e.g. 169.254.169.254).

Fix: Allowlist destinations or constrain the parameter; block private/link-local addresses server-side.

Location: tool set_webhook · inputSchema.properties.url

Tools 79

Each tool and what it can reach — statically extracted from the published source.

  • create_pollnetwork egress
  • delete_local_messagesnetwork egress
  • delete_messagenetwork egress
  • edit_messagenetwork egress
  • export_messagesnetwork egress
  • pin_messagenetwork egress
  • prune_storenetwork egress
  • react_to_messagenetwork egress
  • schedule_messagenetwork egress
  • send_attachmentnetwork egress
Show 69 more tools ↓
  • send_messagenetwork egress
  • send_message_request_responsenetwork egress
  • send_stickernetwork egress
  • set_expiration_timernetwork egress
  • set_typingnetwork egress
  • set_webhooknetwork egress
  • submit_rate_limit_challengenetwork egress
  • terminate_pollnetwork egress
  • unpin_messagenetwork egress
  • vote_pollnetwork egress
  • add_deviceno sensitive capability
  • add_sticker_packno sensitive capability
  • admin_delete_messageno sensitive capability
  • block_contactno sensitive capability
  • cancel_scheduled_messageno sensitive capability
  • clear_local_storeno sensitive capability
  • create_groupno sensitive capability
  • delete_group_messageno sensitive capability
  • find_contactno sensitive capability
  • finish_change_numberno sensitive capability
  • get_attachmentno sensitive capability
  • get_avatarno sensitive capability
  • get_conversationno sensitive capability
  • get_own_numberno sensitive capability
  • get_profileno sensitive capability
  • get_stickerno sensitive capability
  • get_unreadno sensitive capability
  • get_user_statusno sensitive capability
  • get_webhookno sensitive capability
  • import_desktopno sensitive capability
  • join_groupno sensitive capability
  • leave_groupno sensitive capability
  • list_accountsno sensitive capability
  • list_attachmentsno sensitive capability
  • list_contactsno sensitive capability
  • list_conversationsno sensitive capability
  • list_devicesno sensitive capability
  • list_groupsno sensitive capability
  • list_identitiesno sensitive capability
  • list_scheduled_messagesno sensitive capability
  • list_sticker_packsno sensitive capability
  • mark_as_unreadno sensitive capability
  • receive_directno sensitive capability
  • receive_messagesno sensitive capability
  • remove_contactno sensitive capability
  • remove_deviceno sensitive capability
  • remove_pinno sensitive capability
  • run_scheduled_messagesno sensitive capability
  • search_messagesno sensitive capability
  • send_contacts_syncno sensitive capability
  • send_group_attachmentno sensitive capability
  • send_group_messageno sensitive capability
  • send_group_stickerno sensitive capability
  • send_note_to_selfno sensitive capability
  • send_read_receiptno sensitive capability
  • send_sync_requestno sensitive capability
  • set_pinno sensitive capability
  • start_change_numberno sensitive capability
  • store_statsno sensitive capability
  • sync_desktopno sensitive capability
  • trust_identityno sensitive capability
  • unblock_contactno sensitive capability
  • update_accountno sensitive capability
  • update_configurationno sensitive capability
  • update_contactno sensitive capability
  • update_deviceno sensitive capability
  • update_groupno sensitive capability
  • update_profileno sensitive capability
  • upload_sticker_packno sensitive capability

What this scan could not see

Versions 3

Scan history per published version. The engine is deterministic — the same version always yields the same score, so a changed score means the package itself changed.

VersionScoreFindingsEngineScanned
v1.36.0 latest B 83/100 7 1.13.0 2026-09-05
v1.35.1 B 83/100 7 1.13.0 2026-09-04
v1.31.0 B 83/100 6 1.13.0 2026-08-25

Embed this score

Show this server's live Trust Score in your README, docs or website. The badge is served straight from the registry and updates automatically after every rescan — no API key needed. It links back to this page, so anyone who sees the grade can also read the findings behind it instead of taking a number on faith.

MCP Trust Score: B · 83/100
Markdown (GitHub README)
[![MCP Trust Score](https://mcptrustchecker.com/registry/signal-mcp/badge.svg)](https://mcptrustchecker.com/registry/signal-mcp)
HTML
<a href="https://mcptrustchecker.com/registry/signal-mcp"><img src="https://mcptrustchecker.com/registry/signal-mcp/badge.svg" alt="MCP Trust Score" height="20"></a>
Prefer shields.io styling? Point it at https://mcptrustchecker.com/registry/signal-mcp/badge.json via https://img.shields.io/endpoint?url=…

Verify this score yourself

The score above is reproducible: the same package version always yields the same result. Run it locally or over the free API — no account, no LLM, fully deterministic.

npx mcptrustchecker scan signal-mcp --online --registry pypi

Use the free API → How scoring works

Other implementations of Signal 3

Independent packages implementing the same tool, scanned with the same engine. Compare all 4 side by side →

More in AI, Memory & Reasoning