pir-mcp について
pir-mcpは、画像を受け取らずに画面領域の変化や静止を検知したいエージェント向けのMCPサーバーです。粗いグリッドのスコアと時刻のみを返し、画面内容をツール結果に含めません。
主な機能
- 01画面領域とマスクの定義・選択
- 02移動するウィンドウの追跡
- 03RMSEまたはピーク値による変化測定
- 04変化または一定時間の静止を待機
- 05画像やフレームファイルを出力しない
活用シーン
- 01ビルド出力の変化時にエージェントを起動
- 02ステータスバーの更新停止を検知
- 03領域マスクで時計やカーソルを除外
MCP 対応
領域選択、サンプリング、変化検知、静止待機、領域管理のツールをMCPクライアントに提供します。エージェントがツールを呼び出した場合にのみ画面をキャプチャします。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y pir-mcpPIR_CAPTURE_CMDScreenshot command template writing binary PPM to stdout; {x} {y} {w} {h} substituted. Default: grim (wlroots).PIR_SELECT_CMDInteractive rectangle selector printing 'x,y wxh'. Default: slurp. Empty disables the pick tools.PIR_WINDOW_GEOMETRY_CMDPrints 'x,y wxh' for window {id}. Default: Hyprland via jq. Empty disables window regions.PIR_PICK_WINDOW_CMDInteractive window pick printing the window id. Default: Hyprland + slurp.PIR_MAX_WAIT_MSCap for blocking calls, ms (default 540000); keep under the host's MCP tool timeout.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
10掲載時のツール一覧 · 3 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| h | integer | はい | 高さ、ピクセル |
| w | integer | はい | 幅、ピクセル |
| x | integer | はい | 左端、ピクセル |
| y | integer | はい | 上端、ピクセル |
| name | string | はい | |
| masks | array | いいえ |
詳細
pir-mcp
AI エージェント向けのモーションセンサーです。
"LLM エージェントに、Windows Recall のようにプライバシーを脅かすことなく、頼れる「見守り役」となるための十分な情報を提供します"
-Solteris-Dev
PIR センサーが伝えるのは、何かが動いたということだけで、何が動いたかは伝えません。画面向けのこの仕組みも同じです。名前を付けた長方形を監視する MCP サーバーで、「変化したか」「動きが止まったか」を数値、サイズ、タイムスタンプで回答します。ピクセルや画像ファイル、画像に戻せるものを返すツールはありません。
デスクトップを操作するエージェントには、いつも同じ2つのことが必要です。ビルド出力が動いたら知らせて、そしてこのステータスバーの更新が止まったか教えて。どちらも動きについての問いです。スクリーンショットは必要ありません。
できること
pir_pick_region画面上の人に、領域をドラッグして選ぶよう依頼します。範囲を指定してスクリーンショットを撮る場合(slurp、slop)と同じ方法です。何を検知するかは人が選び、エージェントはその位置とサイズを取得します。人がその場にいるときは、これを使ってください。pir_pick_mask領域内で無視する部分(時計、スピナー、キャレット)を同じ操作で選びます。pir_define_regionスクリプトから指定する方法です。グローバルなレイアウト座標で長方形に名前を付け、必要に応じてマスクも設定します。pir_pick_window/pir_define_window固定の長方形ではなく、ウィンドウを監視します。キャプチャの前に毎回ウィンドウの位置とサイズを再取得するため、ウィンドウが移動すると領域も追従します。サイズ変更は最大の変化として扱われます。選択時には、画面に表示されているウィンドウがクリック可能な枠で表示されます。pir_sample一度キャプチャし、その領域の前回のサンプルと比較します。低コストで、キャプチャコマンドが動作するか確認する方法でもあります。pir_wait_for_change呼び出し開始時の見た目から領域が変化するまで待機するか、タイムアウトします。呼び鈴のようなものです。pir_wait_for_stillnessstill_for_msの間、変化がない状態になるまで待機するか、タイムアウトします。短い時間を指定すれば、「アニメーションが落ち着いたので、安全に操作できる」という意味になります。変化し続けるはずの対象に長い時間を指定すると、動きが止まったことを検知します。その場合、still=trueが警告となります。pir_list_regions、pir_remove_region領域の管理を行います。
比較のたびに、平均化した色のセルで構成される粗いグリッドを使って2つの数値を報告します(横方向のセル数は最大64、各セルの幅は最低4 px)。同一ならどちらも0、黒と白を比べると1になります。
rmseグリッド全体での値です。領域全体が動いたかどうかを示します。カーソルの縁やアンチエイリアス処理されたキャレットは約0.02、ダイアログが開くと0.1以上になります。デフォルトの指標で、しきい値は0.05です。peak最も変化した単一セルの値です。その中の何かが動いたかどうかを示します。幅1920のステータスバー内で時計の数字が1つ変わる場合、rmse は0.018(デフォルトでは見えない値)ですが、peak は0.145になります。大きな領域内で小さなものが更新されるはずの場合は、metric=peakを使ってください。
平均化することで、これはカメラではなくセンサーになります。64個のセルから内容を読み取ることはできません。
意図的に行わないこと
- 画像データは一切返しません。スナップショットツールはなく、今後追加する予定もありません。 エージェントが画面を見る必要がある場合は、環境にすでにあるスクリーンショットツールを使用してください。そうすれば、その選択は明示的になり、決定権もあなたにあります。
- フレームをディスクに書き込みません。キャプチャはグリッドに変換するまでの数ミリ秒間メモリ上に保持され、各領域について最後のサンプルのグリッドだけが保存されます。
- 独自にキャプチャすることはありません。サンプルはすべてエージェントが実行したツール呼び出しであり、トランスクリプトに表示されます。また、
pir_pick_regionにはpurpose行があり、描画を始める前にエージェントが記入する必要があります。
これにより明らかになる情報は、許容できるかどうかを判断できるように、ある時点で、ある矩形が、ある程度変化したということです。チャットウィンドウを含む領域では、これは在席情報にあたります。領域は適切に選んでください。サーバーは判断しません。
キャプチャ自体は、設定したコマンドに委任され、あなたの権限で実行されます。デフォルトは grim なので、ここで使われるものが画面にアクセスできるのは、すでに grim に許可した範囲だけです。
インストール
npm の pir-mcp として、また
公式 MCP Registry
の io.github.Solteris-Dev/pir-mcp として公開されているため、ほとんどのクライアントではクローンせずに npx -y pir-mcp で実行できます。
claude mcp add -s user pir -- npx -y pir-mcp
ソースからインストールする場合:
git clone https://github.com/Solteris-Dev/pir-mcp
cd pir-mcp && npm install && npm run build
Node 20 以降と、バイナリ PPM を標準出力に書き込めるスクリーンショットツールが必要です。
キャプチャコマンド
PIR_CAPTURE_CMD はテンプレートです。{x} {y} {w} {h} が置換され、結果は sh -c で実行されます。標準出力にバイナリ PPM(P6)を出力する必要があります。
| 環境 | コマンド |
|---|---|
| wlroots / Hyprland / Sway(デフォルト) | grim -g "{x},{y} {w}x{h}" -t ppm - |
| maim を使用する X11 | maim -g {w}x{h}+{x}+{y} -f png | magick png:- ppm:- |
| ImageMagick を使用する X11 | import -window root -crop {w}x{h}+{x}+{y} +repage ppm:- |
| macOS | screencapture -x -R{x},{y},{w},{h} -t png /dev/stdout | magick png:- ppm:- |
座標はキャプチャツールが使用するものです。wlroots のレイアウトではグローバルレイアウト上の座標になるため、プライマリの左側に配置された出力では x が負になります。
セレクターコマンド
エージェントが pir_pick_region または
pir_pick_mask を呼び出すと PIR_SELECT_CMD が実行され、x,y wxh を出力する必要があります。これらのツールを完全に削除するには、空文字列を設定してください。
| 環境 | コマンド |
|---|---|
| wlroots / Hyprland / Sway(デフォルト) | slurp -f "%x,%y %wx%h" |
| X11 | slop -f "%x,%y %wx%h" |
| macOS | contrib/macos を参照(未テスト) |
ウィンドウコマンド
PIR_WINDOW_GEOMETRY_CMD では {id} が置換され、そのウィンドウの x,y wxh を出力する必要があります。PIR_PICK_WINDOW_CMD は、ユーザーが選択したウィンドウの id を出力する必要があります。どちらもデフォルトでは Hyprland を使用します(jq と slurp -r 経由)。対応するツールを削除するには、いずれかに空文字列を設定してください。ウィンドウ id は、シェルに渡される前に [A-Za-z0-9_.:-] に制限されます。
| 環境 | ジオメトリ | 選択 |
|---|---|---|
| Hyprland(デフォルト) | hyprctl -j clients | jq -r --arg id "{id}" '.[] | select(.address==$id) | "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"' | slurp のボックスとして表示されるウィンドウから選択し、アドレスを出力 |
| Sway | swaymsg -t get_tree | jq -r '.. | select(.id? == {id}) | "\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height)"' | swaymsg -t get_tree | jq -r '.. | select(.visible? == true) | "\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height) \(.id)"' | slurp -r -f '%l' |
| X11 | xdotool getwindowgeometry --shell {id} | awk -F= '/^X/{x=$2}/^Y/{y=$2}/^WIDTH/{w=$2}/^HEIGHT/{h=$2}END{print x","y" "w"x"h}' | xdotool selectwindow |
動作確認済みなのは Hyprland の組み合わせだけです。ほかは各ツールのドキュメントをもとに記述しています。
Claude Code
claude mcp add -s user pir -- npx -y pir-mcp
# or, from a source checkout:
claude mcp add -s user pir -- node /path/to/pir-mcp/dist/stdio.js
ブロッキング呼び出しのデフォルトは 55 秒で、PIR_MAX_WAIT_MS(540 秒)によって上限が設定されています。この上限はホスト側の MCP ツールのタイムアウトより短くしてください。より長く監視する必要があるエージェントは、再度呼び出してください。
その他の設定
| 変数 | デフォルト | 意味 |
|---|---|---|
PIR_REGIONS | 未設定 | 起動時に定義する領域を記した JSON ファイル |
PIR_THRESHOLD | 0.05 | デフォルトの変化しきい値 |
PIR_INTERVAL_MS | 500 | デフォルトのサンプリング間隔 |
PIR_DEFAULT_WAIT_MS | 55000 | ブロッキング呼び出しのデフォルトのタイムアウト |
PIR_MAX_WAIT_MS | 540000 | ブロッキング呼び出しの上限 |
PIR_CAPTURE_TIMEOUT_MS | 10000 | 1 回のキャプチャに許容される時間 |
PIR_SELECT_TIMEOUT_MS | 60000 | 選択範囲を描画するための時間 |
PIR_MAX_CELLS | 64 | 長辺方向のグリッド解像度。小さいほど粗くなり、プライバシーが高まります |
領域ファイルは次のようになります。
[
{ "name": "bar", "x": 0, "y": 0, "w": 1920, "h": 26,
"masks": [{ "x": 1690, "y": 0, "w": 110, "h": 26 }] }
]
例
この仕組みが生まれるきっかけとなった事例です。ステータスバーはプロセスが正常に見える一方で、ときどき何時間もフリーズしていました。時計は毎分更新されるはずなので、3 分間そのままのバーはフリーズしています。
pir_pick_region name=bar purpose="watch the status bar for a freeze"
pir_wait_for_stillness name=bar still_for_ms=180000 metric=peak timeout_ms=540000
still=true が返るのはバーが停止した場合のみです。それ以外の場合、タイムアウト時に still=false が返り、エージェントが再度呼び出します。画面上の内容が見られることは一度もなく、矩形はユーザー自身が描画しました。
コントリビューションの出発点
contrib/macos/ には、AppKit の矩形セレクターとキャプチャ手順が含まれています。見よう見まねで作成されたもので、テストされていません。実際の Mac で実行する場合は、問題を修正して送り返してください。
テスト
npm test
ライセンス
MIT。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。