relay-remotify-mcp について
MCP 対応ホストから remotify.run リレー経由でリモートコンピューターにシェルコマンドを送るローカル MCP サーバーです。コマンドごとの承認または自動実行を選べ、セッション復旧ツールも備えます。
主な機能
- 01リモートシェルコマンドの実行
- 02コマンドごとの承認または自動実行
- 03リモートセッションの作成と確認
- 04停止したリレーセッションの復旧
活用シーン
- 01MCP ホストからリモートコンピューターでコマンドを実行
- 02各リモートコマンドの実行前に承認を求める
- 03リレーセッションが停止した後に作業を再開
MCP 対応
MCP クライアントに `remote_exec`、`remote_session_info`、`remote_session_reset` ツールを提供します。コマンドは remotify.run リレーを経由してリモートリスナーに送られます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y remotify-mcpREMOTIFY_URLRelay to talk to. Override to point at a self-hosted instance.REMOTIFY_KEYシークレットReuse an existing session key instead of creating a new one on startup.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
3掲載時のツール一覧 · 3 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| command | string | はい | リモートマシンで実行するシェルコマンド |
詳細
remotify-mcp
remotify.run リレーを利用して、MCP 互換ホストに remote_exec ツールを提供する MCP サーバーです。
お使いのマシン上で動作し、リレーサーバーの利用は無料です。
インストール
ほとんどのユーザーはインストール不要です。以下の MCP ホストはすべて npx 経由で起動します。
npx -y remotify-mcp@latest
改変する場合は、このリポジトリをクローンし、mcp/ で npm install を実行することもできます。
MCP ホストへの組み込み
以下のホストはすべて同じコマンドで起動し、異なるのは設定ファイルだけです。ホストがサーバーを認識しない場合は、MCP 設定の読み込み元について、各ホストのドキュメントを確認してください。
Claude Code
claude mcp add -s user remotify -- npx -y remotify-mcp@latest
-s user を指定すると、コマンドを実行したディレクトリだけでなく、すべての作業ディレクトリに登録されます。claude mcp list で登録を確認できます。セッション中に /mcp を実行すると、現在のステータスと公開されているツールを確認できます。
Codex CLI
~/.codex/config.toml:
[mcp_servers.remotify]
command = "npx"
args = ["-y", "remotify-mcp@latest"]
OpenCode V2
opencode mcp add remotify --global -- npx -y remotify-mcp@latest
npx を利用するには、Node.js 18 以降が必要です。--global を指定すると、サーバーは ~/.config/opencode/opencode.jsonc で登録され、すべてのプロジェクトで利用できます。省略すると、現在のプロジェクトだけに登録されます。アカウント、API キー、グローバルな npm インストールは不要です。
opencode mcp list または OpenCode 内で /mcps を実行して、接続を確認してください。OpenCode に remote_session_info を呼び出して接続用の 1 行コマンドを両方表示するよう依頼し、選んだコマンドをリモート側に貼り付けてください。監視モードでは、コマンドを実行するたびに承認が求められます。自動モードでは、承認なしで実行されます。
セルフホスト可能なリレーを使う場合は、mcp.servers の下にあるサーバーエントリーに environment を追加してください(OpenCode V2 では env ではなく environment を使います)。
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"servers": {
"remotify": {
"type": "local",
"command": ["npx", "-y", "remotify-mcp@latest"],
"environment": {
"REMOTIFY_URL": "https://remotify.example.com"
}
}
}
}
}
Cursor
すべてのプロジェクトに適用する場合は ~/.cursor/mcp.json、1 つのプロジェクトだけに適用する場合は .cursor/mcp.json を使用します。
{ "mcpServers": { "remotify": { "command": "npx", "args": ["-y", "remotify-mcp@latest"] } } }
その後、Cursor を再起動してください。
Windsurf
~/.codeium/windsurf/mcp_config.json に、同じ形式で設定します。
{ "mcpServers": { "remotify": { "command": "npx", "args": ["-y", "remotify-mcp@latest"] } } }
Claude Desktop
macOS では ~/Library/Application Support/Claude/claude_desktop_config.json、Windows では %APPDATA%\Claude\claude_desktop_config.json を使用します。
{ "mcpServers": { "remotify": { "command": "npx", "args": ["-y", "remotify-mcp@latest"] } } }
その後、アプリを再起動してください。
Gemini CLI
~/.gemini/settings.json:
{ "mcpServers": { "remotify": { "command": "npx", "args": ["-y", "remotify-mcp@latest"] } } }
その他
Continue、Cline、Roo Code、Zed、VS Code 組み込みの MCP なども、それぞれのドキュメントに記載されたファイルで同じ command と args の組み合わせを使用します。スニペットを追加すれば設定は完了です。
セルフホスト可能なリレーへの接続
初期設定では、公開リレー https://relay.remotify.run に接続します。独自のインスタンスを使う場合は、ホストの設定に環境変数を 1 つ追加してください(environment フィールドについては、上記の OpenCode V2 の例を参照してください)。
"env": { "REMOTIFY_URL": "https://remotify.example.com" }
ホストに表示してもらう必要があるもの
接続用の 1 行コマンドは、ツールの結果に含まれる通常のテキストコンテンツブロックで渡されます。これは、上記のすべてのホストが変更せずにモデルへ渡す唯一の情報です。このサーバーは、ホスト固有の機能に依存しません。Claude Code のフック、notifications/progress や notifications/message、MCP リソース、エリシテーションのいずれも必要ありません。後述するフックとデスクトップ通知は、それらに対応するホスト向けの追加機能であり、唯一の接続手段ではありません。
環境
| 変数 | デフォルト | 意味 |
|---|---|---|
REMOTIFY_URL | https://relay.remotify.run | 接続先のリレーです。セルフホストしたインスタンスを指定するには、値を上書きします。 |
REMOTIFY_KEY | (unset) | 起動時に新しいセッションを作成する代わりに、既存のセッションキーを再利用します。 |
REMOTIFY_CHUNK_MS | 5000 | ツールが [pending] を返して、アシスタントにループを続けるよう求めるまでの、1 回の呼び出しあたりのブロック時間です。 |
REMOTIFY_MAX_CHUNKS | 24 | ツールが諦めるまでに連続して返せる、処理が進まない [pending] の上限です。リモートでコマンドが実際に実行中の時間は差し引かれ、この上限にはカウントされません。そのため、実行時間の長いジョブが応答のないリスナーと誤認されることはありません。 |
REMOTIFY_POLL_MS | 500 | リレーの /api/session/<key>/status プローブに対する内部ポーリング間隔です。 |
REMOTIFY_RESULT_TIMEOUT_MS | 30000 | GET /result-{key} のロングポーリングにおける、フェッチごとのタイムアウトです。 |
REMOTIFY_QUICK_TIMEOUT_MS | 10000 | ステータス、プッシュ、セッションに関する HTTP 呼び出しのタイムアウトです。 |
REMOTIFY_MAX_INFLIGHT_MS | 1800000 | コマンドが「実行中」の状態で待機できる時間の絶対上限です。コマンドの実行中にリスナーが停止した場合に、ツールが待ち続けないようにします。また、古い実行中マーカー(前のセッションが停止した際に残ったもの)がこの時間を超えると自動的に消去され、新しいコマンドを実行できます。 |
REMOTIFY_STALE_GRACE_S | 30 | 古い実行中状態をすぐに解消するための猶予時間です。リスナーのハートビートが実行開始時刻よりもこの秒数を超えて新しい場合、実行中のコマンドの実行プロセスが確実に停止しているため、REMOTIFY_MAX_INFLIGHT_MS が経過するのを待たずに詰まった状態を解消します。 |
公開されるツール
remote_exec(command)-commandをリレーに送信し、リスナーが実行するまで待機して、標準出力と標準エラーを結合したテキストを返します。remote_session_info()- まず、そのまま貼り付けて使える 1 行コマンドを(監視ありと自動の両方)と、それぞれの動作を説明する文を示し、続いてセッションの JSON を返します。JSON にはキー、URL、TTL が含まれます。この呼び出し時にセッションを遅延作成するだけで、リスナーの接続に必要な情報をすべてユーザーに渡せます。remote_session_reset({rotate?})- 復旧用の最終手段です。デフォルトでは、詰まったリレーの状態(キュー内のコマンド/結果と実行中マーカー)をそのままのセッションで消去します。キーと接続中のリスナーは引き続き動作します。{"rotate": true}を指定すると、現在のセッションを消去して新しいキーを発行します(ユーザーは新しい 1 行コマンドを貼り直す必要があります)。通常は不要です。remote_execが自動的に復旧します(下記参照)。
応答しなくなったセッションからの自動復旧
リレーに通知する機会がないままコマンド実行中にリスナーが強制終了されると(kill -9、ターミナルの終了、ホストの再起動)、以前はセッションが応答しなくなっていました。新しいコマンドは、現在のセッションが実行したことのないコマンドに対して毎回[busy]を返し、解決するにはダミーの結果を手動で投稿してMCPを再読み込みするしかありませんでした。この状態は自動的に解消されるようになりました。
- **リレー側:**リスナーが再接続して作業をポーリングすると、その時点でリレーは孤立した処理中マーカーを検出してクリアし、結果を待っていた相手に合成された
[remotify: ...]結果をキューに追加します。 - **MCP側:**新しいコマンドがビジーガードにかかり、マーカーが確実に古いと判断できる場合(リスナーのハートビートが取得時刻より
REMOTIFY_STALE_GRACE_S以上新しい場合)、またはマーカーがREMOTIFY_MAX_INFLIGHT_MSより古い場合、MCPはセッション状態自体をリセットします(POST /api/session/{key}/reset。古いリレーの場合は手動クリアにフォールバック)。その後、新しいコマンドを続行し、応答の先頭に[recovered]を付けます。
実際に長時間かかっているコマンドには影響しません。リスナーが実行中のコマンドでビジー状態の間は、ハートビートが取得時刻より新しくなることはないため、REMOTIFY_MAX_INFLIGHT_MSに達するまではクリアされません。
自動で解消できない応答停止のパターンが1つあります。リスナーがコマンド実行中に停止し(ハートビートが取得時刻で止まり、実際に長時間実行中の場合と区別できない)、処理中の上限時間を超えない場合です。この場合は、ユーザーがランナーに再接続する必要があります。そのため、[busy]応答には貼り付け用のワンライナーが含まれ、それをリレーするようアシスタントに指示します。再接続すると、上記のリレー側の自動修復が実行されます。
リレーが配信するメッセージの文言
remote_execがアシスタントに返す実行時文字列([pending]、[busy]、[recovered]、貼り付け用のワンライナーなど)はすべて、テンプレートテーブルから生成されます。リレーはセッションペイロード(mcp_messages.templates。リレーリポジトリのphp/app/mcp-messages.jsonで管理)で、任意のキーの置き換えを配信できます。そのため、文言の改善はリレーのデプロイとともに公開され、npmリリースなしで、キャッシュが古いインストールも含め、次回のセッションであらゆるクライアントに反映されます。このパッケージには、古いリレーやオフライン時の障害に備え、完全なテーブルがフォールバックとして組み込まれています。
意図的にリレーから配信しないもの:ツール名、スキーマ、説明。ホストやユーザーはこれらに基づいて使用を承認するため、変更はバージョン管理されたnpmリリースを通じてのみ行います。
リスナーが見つからない場合のremote_execの動作
MCP サーバーには、ツール呼び出しの途中でユーザーにテキストを表示する手段がありません(Claude Code、Cursorなどは、ツール呼び出し中にMCPサーバーからのnotifications/progressやnotifications/messageを表示しません)。入力要求ダイアログは機能しますが、現在のクライアントではサーバー側から閉じられないため、チャットに古いプロンプトが残ってしまいます。
現在の設計を決めるうえで、もう1つ制約がありました。ツール呼び出しの合間にアシスタントが書くテキストも、確実に表示されるとは限りません。Claude Codeでは一行の「要約済み」スタブに折りたたまれ、ほかのホストでも切り詰められたり非表示になったりします。そのため、「ワンライナーをリレーしてからポーリングを続ける」アシスタントは、オペレーターが貼り付けられる内容を実際には何もリレーできていません。ホストに全文が表示されるのは、アシスタントのターンの最後のメッセージだけです。
そこで、remote_execは[pending]を次の2つの場合に分けます。
- 初回の呼び出しであればセッションを作成し、その後、何が起きてもコマンドがリレーにキューイングされるように送信します。
- セッションの最初のコマンドで、リスナーがまだ一度もポーリングしていない場合、ツールは一切待たずにすぐ応答します。ユーザーがランナーの行を貼り付けるまでは誰もコマンドを取得できず、まだその行も表示されていないため、待っても時間を浪費するだけです。応答は
[pending]となり、(監視ありと自動実行の)両方の貼り付け用ワンライナーを含み、アシスタントに停止してターンを終え、その2行をコードフェンス内にそのまま最終メッセージとして出力するよう指示します。コマンドはキューに残ります。ユーザーがワンライナーを貼り付けるとリスナーがコマンドを取得して実行し、ユーザーの次のメッセージでアシスタントが同じ引数でremote_execを再度呼び出し、出力を取得します。サーバーはターンをまたいで状態を保持するため、コマンドは再度キューイングされず、二重に実行されることもありません。 - それ以外の場合、ツールは約5秒間ポーリングします(
REMOTIFY_CHUNK_MS)。その間にリスナーがコマンドを取得すれば、結果を待って返します。ほとんどの呼び出しはここで完了します。 - 後続の呼び出しでもリスナーがいない場合は、両方の行を含む同じ
[pending]を返します。リスナーがいない場合の[pending]、停止したリスナーによる[busy]状態、セッションの更新、そして諦める際のエラーでも毎回これらの行を再掲するため、アシスタントが一度停止指示を無視しても、次の応答で再び行を確認できます。 - リスナーはオンライン(ハートビートは新しい状態)だが、コマンドの取得がまだ確認されていない場合、ツールはワンライナーを含まない
[pending]を返し、同じ引数での無応答の再試行を求めます。約10回連続で応答した後にのみ諦めます。リレーがコマンドの実行中を確認すると(cmd_in_flight)、応答は[in-flight]に切り替わり、再試行回数の上限はなくなります。 - リスナーがいないのではなく、リレーに到達できない場合は、ステータス確認が一度も成功しなかったことを応答で伝えます。壊れているものとは関係のない行を貼り付けるようユーザーに促すことはありません。まったく到達できないリレー(DNS、接続拒否、タイムアウト)と、
426を返す廃止済みエンドポイントには、それぞれURLと変更内容を示す個別のメッセージが表示されます。
すべての [pending] では、厳守すべきルールも改めて伝えます。ssh、scp、その他の転送手段に決して切り替えず、自分でリスナーを起動しようとしないでください。オペレーターが remotify を選ぶのは、エージェントにシェルアクセスを一切与えないためです。リスナーがいない状況を回避しようとするアシスタントは、製品の目的を損ないます。
REMOTIFY_MAX_CHUNKS(デフォルトは24)は、成果のない待機に対するサーバー内部の上限です。リモートでコマンドが実際に実行中の時間は差し引かれ、上限にはカウントされないため、長時間実行されるジョブ(mongodump、restic、時間のかかるデプロイ)がリスナーの停止と誤認されることはありません。キューに入ったコマンドがリレーから自動的に削除されるのは、成果のない再試行が続いて取得予算を使い切った場合、またはセッションがアイドル状態の TTL によって自然に期限切れとなった場合の、いずれか早い方です。
ユーザーから見た結果は次のとおりです。「Calling remotify...」が数秒表示された後、(リスナーがすでに起動していれば)コマンド出力が表示されます。それ以外の場合は、リモート側で貼り付ける2つのワンライナーを示す、アシスタントからの短い最終メッセージが表示されます。ダイアログも、後に残るUIプロンプトもありません。リスナーが接続した瞬間にキュー内のコマンドが実行され、ユーザーの次のメッセージでその出力を取得します。
モデルに依存しないオペレーターへの通知
上記の指示はすべてツールの結果に含まれており、モデルが無視する可能性があります。ホストによって折りたたまれたツール呼び出しの間にある行を伝えたり、そのうち1つだけを伝えたり、どれも伝えずに、起動方法を誰も知らないリスナーへのポーリングを続けたりすることがあります。モデルの動作にかかわらず、これらの行をオペレーターに表示する仕組みが2つあります。
デスクトップ通知とクリップボード。MCP サーバーはオペレーター自身のマシンで動作します。セッションの発行時、および行を貼り付けることだけが終了手段となるすべての応答(リスナーなしの [pending]、停止したリスナーの [busy]、リスナーなしでの諦め)で、デスクトップ通知を表示して、両方の1行コマンドを示し、監視対象の行をクリップボードにコピーします。同じセッションでは、通知は1分に1回までです。Linux では notify-send(または kdialog)と wl-copy / xclip / xsel を使用します。macOS では osascript と pbcopy を使用します。Windows では msg と clip を使用します。いずれもベストエフォートで動作し、ツールが見つからない場合は何も表示しないため、ヘッドレスマシンでも問題はありません。
| 変数 | デフォルト | 効果 |
|---|---|---|
REMOTIFY_NOTIFY | 1 | 0 にするとデスクトップ通知を無効にします |
REMOTIFY_CLIPBOARD | 1 | 0 にするとクリップボードへのコピーを無効にします |
REMOTIFY_NOTIFY_THROTTLE_MS | 60000 | 同じセッションで通知を送る最短間隔 |
Claude Code フック。remotify-mcp --claude-hook は標準入力から PostToolUse フックのペイロードを読み取り、ツールの結果に接続用の1行コマンドが含まれている場合は、Claude Code 自体がターミナルに表示する systemMessage を返します。そのため、モデルが何も言わなくてもコマンドが表示されます。.claude/settings.json(プロジェクト用)または ~/.claude/settings.json(ユーザー用)に追加します。
{
"hooks": {
"PostToolUse": [
{
"matcher": "mcp__remotify__.*",
"hooks": [
{ "type": "command", "command": "npx -y remotify-mcp@latest --claude-hook" }
]
}
]
}
}
初回実行時の一般的な流れ
- MCP ホストがこのサーバーを起動します。まだ何も起こりません。起動時にはセッションは作成されません。最初の
remote_execまたはremote_session_infoの呼び出し時にセッションが遅延作成され、標準エラー出力に表示されます。remotify: new session a1b2... on remote (supervised): curl -fsSL 'https://relay.remotify.run/r/a1b2...' | bash on remote (auto): curl -fsSL 'https://relay.remotify.run/r/a1b2...?mode=auto' | bash - 最初の
remote_exec呼び出しでセッションが作成されます。まだリスナーがない場合、ツールは待機せずにすぐ[pending]を返し、アシスタントは監視対象と自動実行の両方の貼り付け用1行コマンドを最終メッセージとしてターンを終了します。 - どちらか一方をリモート側で貼り付けます(監視対象ではコマンドごとに
y/Nの確認が表示され、自動実行ではすべてのコマンドがすぐに実行されます)。リスナーが接続し、キューに入ったコマンドを実行します。 - 何でもよいので(たとえば「接続しました」など)返信します。アシスタントは同じ引数で
remote_execを再度呼び出し、出力を返します。以降、リスナーが動作しているときの呼び出しは約0.5~2秒で完了します。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。