mcpField
S
Signal Messaging (via signal-cli)

Signal Messaging (via signal-cli)

ローカル
github.com/joshuawowkコミュニケーション01 週間前に更新

Signal Messaging (via signal-cli) について

既存の signal-cli デーモンを介して Signal メッセージを送受信する非公式 MCP サーバーです。エージェントからの状況通知や質問、許可リクエストを送り、別のサブスクライバーで返信を収集します。

主な機能

  1. 01メッセージ、質問、許可リクエストの送信
  2. 02テキスト返信の収集と絞り込み
  3. 03送受信状態の確認
  4. 04既存の signal-cli デーモンの利用

活用シーン

  1. 01タスク完了の通知
  2. 02作業が止まった際の質問
  3. 03取り消せない操作の前の承認依頼

MCP 対応

stdio 経由で MCP サーバーを提供し、Signal メッセージの送信、返信確認、ヘルスチェック用のツールを公開します。オプションのサブスクライバーが既存の signal-cli デーモンから通知を受信します。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"joshuawowk-signal": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"SIGNAL_SENDER",
"-e",
"SIGNAL_DEFAULT_RECIPIENT",
"-e",
"SIGNAL_RPC_URL",
"-e",
"SIGNAL_TCP_HOST",
"-e",
"SIGNAL_TCP_PORT",
"-e",
"SIGNAL_INBOX_PATH",
"-e",
"SIGNAL_POLL_INTERVAL",
"-e",
"SIGNAL_INBOX_RETENTION_DAYS",
"ghcr.io/joshuawowk/signal-mcp:1.0.1"
],
"env": {
"SIGNAL_SENDER": "<SIGNAL_SENDER>",
"SIGNAL_DEFAULT_RECIPIENT": "<SIGNAL_DEFAULT_RECIPIENT>",
"SIGNAL_RPC_URL": "<SIGNAL_RPC_URL>",
"SIGNAL_TCP_HOST": "<SIGNAL_TCP_HOST>",
"SIGNAL_TCP_PORT": "<SIGNAL_TCP_PORT>",
"SIGNAL_INBOX_PATH": "<SIGNAL_INBOX_PATH>",
"SIGNAL_POLL_INTERVAL": "<SIGNAL_POLL_INTERVAL>",
"SIGNAL_INBOX_RETENTION_DAYS": "<SIGNAL_INBOX_RETENTION_DAYS>"
}
}
}
}
起動コマンドdocker run -i --rm -e SIGNAL_SENDER -e SIGNAL_DEFAULT_RECIPIENT -e SIGNAL_RPC_URL -e SIGNAL_TCP_HOST -e SIGNAL_TCP_PORT -e SIGNAL_INBOX_PATH -e SIGNAL_POLL_INTERVAL -e SIGNAL_INBOX_RETENTION_DAYS ghcr.io/joshuawowk/signal-mcp:1.0.1
設定が必要な環境変数
SIGNAL_SENDERE.164 number of the account registered in signal-cli (e.g. +15555550100)
SIGNAL_DEFAULT_RECIPIENTE.164 number messaged by default; tools accept a per-call recipient override
SIGNAL_RPC_URLsignal-cli HTTP JSON-RPC endpoint as seen from the container. The server's built-in default is http://127.0.0.1:8080/api/v1/rpc (use with --network host on Linux); this listing defaults to the Docker host alias.
SIGNAL_TCP_HOSTsignal-cli daemon TCP host, used only for the receive-path health check
SIGNAL_TCP_PORTsignal-cli daemon TCP port (daemon started with --tcp), used only for the receive-path health check
SIGNAL_INBOX_PATHPath of the replies inbox file inside the container (populated only by the subscriber process)
SIGNAL_POLL_INTERVALSubscriber poll cadence in seconds
SIGNAL_INBOX_RETENTION_DAYSDays of replies kept in the inbox file

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
ocighcr.io/joshuawowk/signal-mcp:1.0.1

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

signal-mcp

Release License: MIT

signal-cli を介して Signal と連携する、非公式の MCP 統合です。MCP クライアントから Signal メッセージ(タスク完了通知、作業を妨げる質問、権限リクエスト)を送信し、返信を読み取ることができます。

要件: 稼働中の signal-cli JSON-RPC デーモン(signal-cli daemon --http ...。返信も受信する場合は --tcp ... も指定)と、signal-cli に登録済みの Signal 電話番号が必要です。このプロジェクトは電話番号の登録、デーモンの起動、Signal のサーバーとの直接通信は行いません。デーモンのクライアントとしてのみ動作します。Signal Messenger または Signal Foundation とは提携しておらず、承認も受けていません。

MCP サーバー(app/server.py)と、既存の signal-cli デーモンの前段として動作する任意の返信サブスクライバー(app/subscriber.py)で構成されています。再登録やデータディレクトリのバインドマウントは必要ありません。

インストール

イメージは ghcr.io/joshuawowk/signal-mcp で公開されており、io.github.joshuawowk/signal-mcp として MCP Registry に掲載されています。引数なしで実行すると、コンテナは返信サブスクライバーを起動します(以下の Compose デプロイで使用する長時間実行モードです)。MCP サーバーは明示的に起動します。

stdio 経由の MCP クライアント(送信のみ)
docker run -i --rm \
  --add-host host.docker.internal:host-gateway \
  -e SIGNAL_SENDER=+15555550100 \
  -e SIGNAL_DEFAULT_RECIPIENT=+15555550101 \
  -e SIGNAL_RPC_URL=http://host.docker.internal:8080/api/v1/rpc \
  ghcr.io/joshuawowk/signal-mcp:latest python3 /app/server.py --stdio

注意事項:

  • Linux では、代わりに --network host を使用し、--add-host と SIGNAL_RPC_URL の設定を省略できます(デフォルトの 127.0.0.1:8080 からデーモンにアクセスできます)。
  • ブリッジネットワークを使う場合、デーモンはコンテナからアクセス可能でなければなりません。127.0.0.1 のみにバインドされたデーモンにはアクセスできません。signal-cli の HTTP エンドポイントには認証がありません。信頼できるインターフェース以外には公開しないでください。
  • 単独の stdio コンテナにはサブスクライバーがないため、返信は収集されません。signal_check_replies は何も返さず、signal_health は受信経路がダウンしていると報告します。返信を受信するには、以下の Compose デプロイを使用してください。
Compose デプロイ(送信と返信の受信)

セットアップを参照してください。

アーキテクチャ

MCP client ──stdio──> docker exec ──> python3 /app/server.py ─┐
                                                                  │ HTTP JSON-RPC
host: signal-cli-daemon.service  ◀── 127.0.0.1:8080 (synchronous)─┤  (send, version)
                                  ◀── 127.0.0.1:7583 (TCP stream)─┤  (receive notifications)
                                                                  │
       docker container (signal-mcp, restart=unless-stopped)      │
       PID 1: subscriber.py ── persistent TCP socket ─────────────┘
                            └─> append /data/inbox.jsonl  ◀── signal_check_replies reads
  • signal-cli のデータはバインドマウントしません。 コンテナはホストのデーモンのクライアントとしてのみ動作します。Signal の ID キーがコンテナに入ることはありません。
  • 再登録は不要です。 Signal の ID はホスト上に保持されます。
  • 2 チャネルのデーモンです。 同期呼び出し(送信、バージョン、ヘルスチェック)は :8080 の HTTP 経由で行います。受信メッセージの通知は、永続的な TCP ソケット(:7583)を介してストリーミングされます。HTTP デーモンの receive メソッドは、signal-cli の内部自動受信ループによって恒久的にロックされるため、返信に使える経路は TCP のみです。
  • デーモンに追加するフラグは 1 つです。 既存の signal-cli-daemon.service の ExecStart に --tcp 127.0.0.1:7583 引数を追加します(下記の「デーモンの設定」を参照)。他の利用者に対する HTTP の動作は変わりません。

セットアップ

git clone https://github.com/joshuawowk/signal-mcp && cd signal-mcp
cp .env.example .env       # set SIGNAL_SENDER and SIGNAL_DEFAULT_RECIPIENT
docker compose build
docker compose up -d
docker compose logs -f signal-mcp   # watch the subscriber start up

コンテナからデーモンにアクセスできることを確認します。

docker exec signal-mcp python3 -c \
  "import rpc; print(rpc.ping())"
# expected: 0.14.3
Claude Desktop に MCP サーバーを登録する

claude_desktop_config.snippet.json の内容を ~/.config/Claude/claude_desktop_config.json の mcpServers の下にマージします。

"signal": {
  "command": "sg",
  "args": ["docker", "-c", "exec docker exec -i signal-mcp python3 /app/server.py"]
}

Claude Desktop を再起動します。

sg ラッパーを使う理由

sg docker -c "…" は、docker 補助グループの権限でコマンドを実行します。Claude Desktop プロセスの起動後にユーザーを docker グループに追加した場合は、これが必要です。既存のセッションは古い補助グループの一覧を引き継ぐため、docker exec は permission denied while trying to connect to the docker API at unix:///var/run/docker.sock を返します。このエラーは Claude Desktop のログでは write EPIPE / Server transport closed unexpectedly として表示されます。

-c 文字列内の exec によって、sg が起動した一時的な bash が docker exec プロセスに置き換わります。そのため、接続が閉じたときに Claude Desktop から送られる SIGTERM/SIGPIPE が MCP サーバーに正しく届きます。

ログアウトして再度ログインする(または再起動する)と、新しいプロセスはすべて docker グループを引き継ぐため、ラッパーは必須ではありません。ただし、残しておいても問題はなく、グループの設定が異なる可能性のあるホスト間で設定を移植可能にできます。signal サーバーが MCP サーバーの一覧に表示され、そのツール(signal_send_message、signal_send_question、signal_send_permission_request、signal_check_replies、signal_health)をどのセッションでも利用できるようになります。

コンパニオンスキルをインストールする

スキルの例は skill/SKILL.md にあります(1 人の環境向けに書かれているため、名前や文言を調整してください)。エージェントのスキルディレクトリにコピーまたはシンボリックリンクを作成します。例:

mkdir -p <your-skills-dir>/signal
ln -sf "$PWD/skill/SKILL.md" <your-skills-dir>/signal/SKILL.md

Claude セッションからのエンドツーエンドテスト

Use signal_health to confirm the daemon is up, then signal_send_message
with text="signal-mcp end-to-end test from session XYZ" and
session_id="signal-mcp-test-001". Then wait 30 seconds and call
signal_check_replies with session_id="signal-mcp-test-001".

スマートフォンから何か返信してください。次の signal_check_replies 呼び出しで、メッセージが返されるはずです。

ツール

ツール呼び出すタイミング
signal_send_message(text, recipient?, session_id?)タスク完了の通知や参考情報の共有に使います。返信は不要です。
signal_send_question(question, options?, recipient?, session_id?)作業がブロックされ、回答が必要なときに使います。options はリスト ["A","B"]、JSON 配列の文字列 '["A","B"]'、または改行/カンマ区切りのテキストを受け付けます。いずれもサーバー側で正規化されます。応答には options_parsed が含まれます。
signal_send_permission_request(action, context, recipient?, session_id?)取り消せない操作を実行する前に使います。明示的な YES を待ってください。
signal_check_replies(since?, from_recipient?, session_id?, limit?)返信をポーリングします。session_id で絞り込めます。
signal_health()完全なヘルスチェックを実行します。送信経路(デーモン HTTP)、受信経路(TCP ポートとサブスクライバープロセスの稼働状況)、受信トレイの状態を確認します。ok が true になるのは、送信と受信の両方が正常な場合のみです。受信トレイが空でも問題ありません。何か失敗した場合は、まず実行してください。
信頼性に関する注意事項(2026年6月)
  • 受信トレイのファイル(/data/inbox.jsonl)はサブスクライバーの起動時に作成され、保持期間に基づく削除では消去されません。受信トレイが空の場合も、0 バイトのファイルとして残ります。以前は、すべてのレコードが期限切れになる(保持期間は 14 日)と削除処理によってファイル自体が削除され、サブスクライバーが停止しているように signal_check_replies/signal_health に表示されていました。signal_check_replies と signal_health は、呼び出しのたびにファイルが存在することも確認します。
  • signal_health と signal_check_replies は、subscriber_running(/proc をスキャンして subscriber.py を確認)と receive_channel_ok(デーモンの :7583 への TCP 接続)を報告します。これにより、新しいセッションでも「まだ返信がない」のか「受信経路に問題がある」のかを区別できます。
  • signal_send_question は、options リストを文字列にシリアライズするクライアントにも対応します(「ツール」表を参照)。

設定(.env)

変数意味
SIGNAL_SENDER登録済み signal-cli アカウントの E.164 番号です。必須です。
SIGNAL_DEFAULT_RECIPIENTデフォルトで通知を送る E.164 番号です。必須です。
SIGNAL_RPC_URLコンテナから見たデーモンのエンドポイントです。デフォルトは http://127.0.0.1:8080/api/v1/rpc です。network_mode: host の場合は、そのまま使用できます。
SIGNAL_TCP_HOST / SIGNAL_TCP_PORT受信通知用のデーモン TCP ストリームです。デフォルトはそれぞれ 127.0.0.1/7583 です。
SIGNAL_POLL_INTERVALサブスクライバーがポーリングする間隔(秒)です。
SIGNAL_INBOX_RETENTION_DAYSinbox.jsonl に返信を保持する日数です。
SIGNAL_INBOX_PATHコンテナ内の受信トレイファイルのパスです。

運用

docker compose ps                       # status
docker compose logs -f signal-mcp       # subscriber output
docker exec signal-mcp tail -f /data/inbox.jsonl   # raw replies
docker compose restart signal-mcp       # bounce the container
docker compose down                     # stop

ホストのデーモンが再起動すると、サブスクライバーは次のポーリング時に再接続します(エラーが発生した場合、最大60秒まで待機時間が延長されます)。

注意事項と制限

  • Linux ホストのみ対応しています。 network_mode: host は、macOS/Windows の Docker Desktop では何も行いません。移行するには、ブリッジネットワークに切り替え、SIGNAL_RPC_URL=http://host.docker.internal:8080/api/v1/rpc を設定し、extra_hosts: ["host.docker.internal:host-gateway"] を追加してください。
  • HTTP デーモンのポーリング。 signal-cli の HTTP モードでは受信イベントをストリーミングできないため、ポーリングを行います。WebSocket サブスクリプションに対応した TCP モードのデーモンなら遅延を抑えられますが、既存のデーモンサービスを変更する必要があります。
  • 添付ファイルはスキップされます。 サブスクライバーが保存するのはテキスト本文のみです。リアクション、入力中インジケーター、既読通知は無視されます。
  • 電話番号は記憶されません。 電話番号は .env と登録用スニペットにのみ保存され、どちらもこのプロジェクト内にあります。

デーモンの設定

このプロジェクトでは、ホストの signal-cli-daemon.service が、同期呼び出し用の HTTP とストリーミング受信通知用の TCP の両方を公開している必要があります。 ~/.config/systemd/user/signal-cli-daemon.service にあるユニットファイルには、次の設定が必要です。

ExecStart=/usr/local/bin/signal-cli -a +15555550100 daemon --http 127.0.0.1:8080 --tcp 127.0.0.1:7583 --receive-mode on-start

変更を適用するには、次の手順を実行してください。

systemctl --user daemon-reload
systemctl --user restart signal-cli-daemon.service

signal-mcp を初めてセットアップすると、元のユニットファイルのバックアップが、稼働中のファイルと同じ場所に .bak.YYYYMMDD-HHMMSS というサフィックスを付けて作成されます。

受信に HTTP を使わない理由

signal-cli の HTTP デーモンモードは同期処理専用です。HTTP 経由の receive は常に "Receive command cannot be used if messages are already being received" というエラーになります。これは、デーモン内部の受信ループがキューを管理しており、HTTP にはプッシュイベントを配信する方法がないためです。TCP モードでは、改行区切りの JSON-RPC ストリームを常時接続で開き、到着した receive 通知をプッシュします。subscriber.py が使用するのはこの方法です。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。