loading…
Search for a command to run...
loading…
Local Signal MCP server: read via Signal Desktop, send via signal-cli
Python uv MCP License: MIT GitHub issues GitHub stars Sealjay/mcp-signal MCP server
A local Model Context Protocol (MCP) server that reads Signal Desktop history from the local encrypted database via signal-export and sends outbound messages via signal-cli.
mcp-signal focuses on the core workflow for personal Signal automation — list chats, read messages, search messages, inspect groups, and send messages to direct or group chats. Everything runs locally; stdio transport with no network listener.
Heads up — mixed backend. Read/search comes from the local Signal Desktop database. Sending uses
signal-cli, which must be installed and linked to a Signal account separately. Ifsignal-cliis unavailable, read/search still works but send tools do not.
signal-cli group IDs for outbound useClone this repository
git clone https://github.com/Sealjay/mcp-signal.git
cd mcp-signal
Install dependencies
uv sync
Install signal-cli (optional — only needed for outbound sends)
On macOS, the simplest route is Homebrew:
brew install signal-cli
The server auto-loads a local .env.local file from the repo root if present. This file is gitignored and is the recommended place for machine-local config.
cat > .env.local <<'EOF'
SIGNAL_ACCOUNT="+441234567890"
EOF
Optional environment variables:
| Variable | Purpose |
|---|---|
SIGNAL_CLI_PATH |
Override the signal-cli binary path |
SIGNAL_DATA_DIR |
Override the Signal Desktop data directory |
SIGNAL_DB_PASSWORD |
Password for encrypted desktop DBs if needed |
SIGNAL_DB_KEY |
Raw key for encrypted desktop DBs if needed |
Environment variables set in the shell take precedence over .env.local.
signal-cli (first run only)mcp-signal does not manage linking itself. Link the local signal-cli device first:
signal-cli link -n "signal-mcp"
Scan the QR code in the Signal mobile app (Settings → Linked Devices → Link New Device).
Do not pass -a / --account to link on current signal-cli versions — linking a new secondary device does not take a phone number there.
After the QR is accepted, confirm the linked account is visible:
signal-cli listAccounts
That account should match the SIGNAL_ACCOUNT value in .env.local.
signal-cli stores its linked-account state under its own local data directory (typically ~/.local/share/signal-cli/data on macOS/Linux). That state lives outside this repository and is not committed by mcp-signal.
Verify everything is connected:
uv run signal-mcp smoke
All clients launch the server the same way over stdio. On macOS, you may need the absolute path to uv — see macOS: uv PATH below.
The quickest route is the CLI:
claude mcp add --transport stdio signal --scope user -- uv run --directory /absolute/path/to/mcp-signal signal-mcp serve
Alternatively, add to .mcp.json at your project root (or ~/.claude.json for a user-scoped server):
{
"mcpServers": {
"signal": {
"type": "stdio",
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/mcp-signal", "signal-mcp", "serve"]
}
}
}
If you edit the file directly, restart the Claude Code session to pick it up.
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"signal": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/mcp-signal", "signal-mcp", "serve"]
}
}
}
Restart Claude Desktop. You should see signal listed as an available integration.
Add to ~/.cursor/mcp.json:
{
"mcpServers": {
"signal": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/mcp-signal", "signal-mcp", "serve"]
}
}
}
Restart Cursor.
uv PATHGUI apps (Claude Desktop, Cursor) don't always inherit the PATH from your interactive terminal, so uv may fail with spawn uv ENOENT. Fix by using the absolute path to uv in command:
/opt/homebrew/bin/uv (Apple Silicon) or /usr/local/bin/uv (Intel)which uv in your terminal to find itExample:
{
"mcpServers": {
"signal": {
"command": "/opt/homebrew/bin/uv",
"args": ["run", "--directory", "/absolute/path/to/mcp-signal", "signal-mcp", "serve"]
}
}
}
| Component | Description |
|---|---|
| MCP server | Python/FastMCP, stdio transport |
| Read path | signal-export reading the local Signal Desktop database |
| Send path | signal-cli JSON-RPC launched on demand |
| State | No separate cache; reads directly from Signal Desktop data |
signal-mcp serve over stdio.signal-export against the local Signal Desktop database.signal-cli -a ACCOUNT jsonRpc.mcp-signal/
src/mcp_signal/
config.py
main.py
reader.py
server.py
signal_cli.py
tests/
CLAUDE.md
LICENSE
README.md
SECURITY.md
| 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 |
send_message |
Send a text message to a direct recipient or group |
get_status |
Show desktop DB / signal-cli / account readiness |
signal-cli account..env.local is intended for local secrets such as SIGNAL_ACCOUNT and is not committed.signal-cli linked-device state is stored in its own local app data directory, outside this repo, and is not committed.See SECURITY.md for how to report vulnerabilities.
signal-cli.signal-cli: local DB reads alone do not provide enough information to send to groups safely.uv sync
uv run signal-mcp smoke
uv run pytest
uv run ruff check .
signal-cli not found — confirm signal-cli is on PATH or set SIGNAL_CLI_PATH in .env.local. On macOS, brew install signal-cli is the simplest route.signal-cli is not linked or SIGNAL_ACCOUNT is not set. Run signal-cli listAccounts to verify, then check .env.local.signal-cli link hangs or fails — do not pass -a / --account to link on current versions. Run signal-cli link -n "signal-mcp" and scan the QR from your phone.args must contain an absolute path to the repo, not relative. If uv itself fails with spawn uv ENOENT, see macOS: uv PATH.Contributions welcome via pull request. Please:
uv run ruff check . before pushing.uv run pytest passes.See CLAUDE.md for the full development workflow.
MIT Licence — see LICENSE.
Добавь это в claude_desktop_config.json и перезапусти Claude Desktop.
{
"mcpServers": {
"mcp-signal": {
"command": "npx",
"args": []
}
}
}