mcp-signal
mcp-signal
Локальный сервер протокола контекста модели (MCP), который считывает историю Signal Desktop из локальной зашифрованной базы данных через
signal-exportи отправляет исходящие сообщения черезsignal-cli.
mcp-signal фокусируется на основном рабочем процессе для личной автоматизации Signal — список чатов, чтение сообщений, поиск по сообщениям, просмотр групп и отправка сообщений в личные или групповые чаты. Все работает локально; используется транспорт stdio без сетевого прослушивателя.
Внимание — смешанный бэкенд. Чтение/поиск осуществляется из локальной базы данных Signal Desktop. Для отправки используется
signal-cli, который должен быть установлен и привязан к учетной записи Signal отдельно. Еслиsignal-cliнедоступен, чтение/поиск будут работать, но инструменты отправки — нет.
Функции
Список личных и групповых чатов из Signal Desktop
Чтение последних сообщений из чата
Поиск сообщений в одном чате или по всем чатам
Список групповых чатов с идентификаторами групп
signal-cliдля исходящих сообщенийОтправка сообщения:
прямому получателю по номеру телефона
в группу по идентификатору группы
в чат по точному названию чата (с проверкой неоднозначности)
Работает полностью на вашем компьютере; транспорт stdio без сетевого прослушивателя
Related MCP server: Signal MCP
Настройка
Предварительные требования
Python 3.13+
Signal Desktop с существующей локальной базой данных сообщений
signal-cli, установленный и привязанный, если вы хотите отправлять сообщения
Установка
Клонируйте этот репозиторий
git clone https://github.com/Sealjay/mcp-signal.git cd mcp-signalУстановите зависимости
uv syncУстановите
signal-cli(необязательно — нужно только для исходящих сообщений)В macOS проще всего использовать Homebrew:
brew install signal-cli
Настройка исходящих сообщений
Сервер автоматически загружает локальный файл .env.local из корня репозитория, если он существует. Этот файл игнорируется git и является рекомендуемым местом для локальной конфигурации машины.
cat > .env.local <<'EOF'
SIGNAL_ACCOUNT="+441234567890"
EOFНеобязательные переменные окружения:
Переменная | Назначение |
| Переопределить путь к бинарному файлу |
| Переопределить директорию данных Signal Desktop |
| Пароль для зашифрованных баз данных Desktop, если требуется |
| Ключ для зашифрованных баз данных Desktop, если требуется |
Переменные окружения, установленные в оболочке, имеют приоритет над .env.local.
Привязка signal-cli (только при первом запуске)
mcp-signal не управляет привязкой самостоятельно. Сначала привяжите локальное устройство signal-cli:
signal-cli link -n "signal-mcp"Отсканируйте QR-код в мобильном приложении Signal (Настройки → Связанные устройства → Связать новое устройство).
Не передавайте -a / --account в команду link в текущих версиях signal-cli — привязка нового вторичного устройства не требует номера телефона.
После того как QR-код будет принят, убедитесь, что связанная учетная запись видна:
signal-cli listAccountsЭта учетная запись должна соответствовать значению SIGNAL_ACCOUNT в .env.local.
signal-cli хранит состояние связанной учетной записи в своей собственной локальной директории данных (обычно ~/.local/share/signal-cli/data в macOS/Linux). Это состояние находится вне этого репозитория и не коммитится в mcp-signal.
Проверьте, что все подключено:
uv run signal-mcp smokeКонфигурация MCP-клиента
Все клиенты запускают сервер одинаково через stdio. В macOS вам может потребоваться абсолютный путь к uv — см. macOS: uv PATH ниже.
Claude Code
Самый быстрый путь — через CLI:
claude mcp add --transport stdio signal --scope user -- uv run --directory /absolute/path/to/mcp-signal signal-mcp serveАльтернативно, добавьте в .mcp.json в корне вашего проекта (или ~/.claude.json для сервера на уровне пользователя):
{
"mcpServers": {
"signal": {
"type": "stdio",
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/mcp-signal", "signal-mcp", "serve"]
}
}
}Если вы редактируете файл напрямую, перезапустите сессию Claude Code, чтобы изменения вступили в силу.
Claude Desktop
Добавьте в ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"signal": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/mcp-signal", "signal-mcp", "serve"]
}
}
}Перезапустите Claude Desktop. Вы должны увидеть signal в списке доступных интеграций.
Cursor
Добавьте в ~/.cursor/mcp.json:
{
"mcpServers": {
"signal": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/mcp-signal", "signal-mcp", "serve"]
}
}
}Перезапустите Cursor.
macOS: uv PATH
Графические приложения (Claude Desktop, Cursor) не всегда наследуют PATH из вашего интерактивного терминала, поэтому uv может выдать ошибку spawn uv ENOENT. Исправьте это, используя абсолютный путь к uv в command:
Homebrew —
/opt/homebrew/bin/uv(Apple Silicon) или/usr/local/bin/uv(Intel)Ручная установка — выполните
which uvв терминале, чтобы найти путь
Пример:
{
"mcpServers": {
"signal": {
"command": "/opt/homebrew/bin/uv",
"args": ["run", "--directory", "/absolute/path/to/mcp-signal", "signal-mcp", "serve"]
}
}
}Архитектура
Компонент | Описание |
MCP-сервер | Python/FastMCP, транспорт stdio |
Путь чтения |
|
Путь отправки |
|
Состояние | Нет отдельного кэша; чтение напрямую из данных Signal Desktop |
Поток данных
MCP-клиент запускает
signal-mcp serveчерез stdio.Инструменты чтения/поиска вызывают
signal-exportдля локальной базы данных Signal Desktop.Список групп и исходящие сообщения вызывают
signal-cli -a ACCOUNT jsonRpc.Результаты возвращаются в виде структурированного JSON.
Структура проекта
mcp-signal/
src/mcp_signal/
config.py
main.py
reader.py
server.py
signal_cli.py
tests/
CLAUDE.md
LICENSE
README.md
SECURITY.mdИнструменты
Инструмент | Назначение |
| Список личных и групповых чатов из Signal Desktop |
| Чтение сообщений из конкретного чата |
| Поиск сообщений в одном чате или по всем чатам |
| Список групп из |
| Отправка текстового сообщения прямому получателю или в группу |
| Показать состояние БД Desktop / |
Конфиденциальность и безопасность
Нет облачного ретранслятора. Нет сетевого прослушивателя. Все данные остаются на вашем компьютере.
Чтение/поиск использует только ваши локальные данные Signal Desktop.
Операции отправки требуют локально настроенной учетной записи
signal-cli..env.localпредназначен для локальных секретов, таких какSIGNAL_ACCOUNT, и не коммитится.Состояние связанного устройства
signal-cliхранится в его собственной локальной директории данных приложения, вне этого репозитория, и не коммитится.
См. SECURITY.md для получения информации о том, как сообщать об уязвимостях.
Ограничения
Риск инъекции промптов: как и многие MCP-серверы, этот подвержен смертельному трио. Вредоносные входящие сообщения могут попытаться дать агенту команду на эксфильтрацию других сообщений. Относитесь к поверхности инструментов соответствующим образом и проверяйте исходящие действия перед их одобрением.
Смешанный бэкенд: история чатов берется из Signal Desktop, а исходящие сообщения — из
signal-cli.Нет вложений: отправка только текста.
Нет уведомлений в реальном времени: только опрос/чтение.
Одна учетная запись на экземпляр MCP.
Для отправки в группы нужен
signal-cli: одного чтения локальной БД недостаточно для безопасной отправки в группы.
Разработка
uv sync
uv run signal-mcp smoke
uv run pytest
uv run ruff check .Устранение неполадок
signal-cliне найден — убедитесь, чтоsignal-cliнаходится вPATH, или установитеSIGNAL_CLI_PATHв.env.local. В macOS проще всего использоватьbrew install signal-cli.Чтение/поиск работают, но отправка не удается —
signal-cliне привязан или не установленSIGNAL_ACCOUNT. Выполнитеsignal-cli listAccountsдля проверки, затем проверьте.env.local.signal-cli linkзависает или выдает ошибку — не передавайте-a/--accountвlinkв текущих версиях. Выполнитеsignal-cli link -n "signal-mcp"и отсканируйте QR-код с телефона.MCP-клиент не может запустить сервер —
argsдолжны содержать абсолютный путь к репозиторию, а не относительный. Если самuvвыдает ошибкуspawn uv ENOENT, см. macOS:uvPATH.Сообщения не возвращаются — убедитесь, что Signal Desktop установлен и имеет историю сообщений. Путь чтения запрашивает локальную базу данных Signal Desktop напрямую.
Участие в разработке
Приветствуются вклады через pull request. Пожалуйста:
Выполните
uv run ruff check .перед отправкой.Убедитесь, что
uv run pytestпроходит успешно.
См. CLAUDE.md для полного рабочего процесса разработки.
Лицензия
Лицензия MIT — см. LICENSE.
Available Tools
9 toolschat_activityChat ActivityARead-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.
Inputs: limit. Returns: result
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.
Inputs: local_key (required), encrypted_path (required). Returns: result
get_statusGet StatusARead-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.
Inputs: no named parameters. Returns: object
list_chatsList ChatsARead-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.
Inputs: limit, query. Returns: result
list_groupsList GroupsARead-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.
Inputs: limit, query. Returns: result
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.
Inputs: no named parameters. Returns: object
read_messagesRead MessagesARead-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.
Inputs: chat_name (required), after, limit, before, +1 more. Returns: result
search_messagesSearch MessagesARead-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.
Inputs: query (required), limit, chat_name. Returns: result
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.
Inputs: message (required), group_id, chat_name, phone_number. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 9 tools
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.
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.
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.
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
Related MCP Connectors
Your own WhatsApp as an MCP server: read, search and send from any MCP client.
MCP connector for iMessage & Contacts via a local Mac agent + Vercel relay
Unified messaging MCP server: WhatsApp, Instagram, Telegram, SMS, Messenger & email support inbox
Drive WhatsApp from any MCP client: pair devices, send text and media, manage contacts and groups.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceMCP Server for retrieving Signal messages using signal-export logic.8-
- AlicenseAqualityBmaintenanceThe most complete Signal MCP server and CLI.81168 PyPI12MIT
- FlicenseNot gradedqualityDmaintenanceMCP server for Signal via signal-cli that enables sending and receiving messages, managing contacts and groups, and reacting over stdio.8 npm-
- AlicenseNot gradedqualityBmaintenanceMCP 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.72-