title: "「入れてくれない」機械ほど、AIエージェントが本来行くべき場所である" description: "Citrix、VDI、踏み台サーバー、そして顧客所有の端末は、いずれも被制御側にランタイムをインストールする方式を一様に拒みます。DeskVNC は、その機械たちがすでに喋っているプロトコルで AI エージェントを届け、遠端には何も入れず、しかも人がいつでも制御を取り戻せます。" date: 2026-10-09 tags: ["リモートデスクトップ", "ai-エージェント", "mcp", "vnc", "rdp", "ssh", "citrix", "vdi"]
RDP での接続しか許さない Citrix ファーム。新しいサービスを一切受け付けない踏み台サーバー。標準のリモート支援ツールだけをホワイトリストに入れている、顧客所有のノートパソコン。一見するとばらばらの三台ですが、たった一つの点で見事に足並みをそろえています。被制御側に新しいランタイムをインストールすることが、許されていないという点です。
皮肉なことに、それはまさに多くの自動化プロジェクトが触れたいと願っている一群の機械でもあります。RPA プラットフォームは、スクリーンショットを撮り、入力イベントを待ち受けて、制御面にデータを送り返す小さな常駐サービスをデスクトップにインストールします。開発者のラップトップではこれが実にうまく動きます。しかし本番環境に持ち出すと、次々と壁にぶつかります。被制御側がインストールを拒むというのは例外ではなく、規制環境や運用が成熟した環境で最も一般的な本番エンドポイントのデフォルト姿勢です。
「エージェントで自動化したい」と言った瞬間に、その対象は最も触れにくい機械たちであるという皮肉な構図が、産業全体の足かせになってきました。壁をくぐり抜ける鍵は、別の場所にありました。
壁をくぐり抜ける扉は、プロトコルの中にあります。以下、順を追って解きほぐします。
インストール型エージェントを拒む六つの機械
以下の六つは別々の事情に見えますが、結論は一つです。被制御側に新しいソフトウェアを入れさせてくれない。RPA の自動化プログラムは、対象を「インストールできる機械」と「インストールできない機械」に分けて、後者を「自動化できない箱」リストに追いやることが、長年のデフォルトでした。DeskVNC はそのリストを空に近いところまで縮めます。
Citrix のパブリッシュアプリと RemoteApp。 ユーザーが端末で見ているのはアプリの一枚窓だけで、プロセスもファイルシステムもクリップボードも GPU も、データセンターの Citrix ホスト側で動いています。被制御側という概念そのものが存在せず、インストール先となる「あの機械」はありません。端末はただのレンダラーであり、ホストは共有され、グループポリシーで固くロックされ、イメージ管理チームが RPA ランタイムを入れることを許しません。
プール型の VDI デスクトップ。 ユーザーがサインインするたびに、ゴールデンイメージから派生した真新しいデスクトップが配られ、サインアウトで返却されます。ユーザープロファイルはリダイレクトされ、ディスクは仕様上非永続的です。ユーザー側にインストールしたものはセッションと一緒に捨て去られ、システム側にインストールしたものはイメージの規約違反になります。
踏み台サーバーと要塞ゲートウェイ。 踏み台サーバーの仕事は、何かを拒むことです。セキュリティチームが選んだ数種類のプロトコルだけを通します。新しいソフトウェアのインストールを許した瞬間、それはもう踏み台サーバーではなくなり、監査面が一晩で膨れ上がります。
顧客所有で厳格に管理されたワークステーション。 顧客側の IT チームがアプリケーションのホワイトリストを敷き、AppLocker や MDM を動かし、ローカル管理者権限を剥奪し、未知のバイナリを止めます。代理店が何かをインストールしたければ、何ヶ月もかける調達手続きが必要になります。
キオスクとシェル差し替え。 機械全体が、一つのアプリか一つの Web ページだけを動かし、それ以外を一切表示しないように作り変えられています。Explorer は置き換えられ、タスクマネージャーは閉じられ、署名済みイメージが正規のフローで配布されます。別のバイナリの起動を許すようなシェルは、もはやキオスクのシェルではありません。
ロックダウンされたサーバーイメージ。 多くの場合 Windows Server Core で、デスクトップすらず、Explorer もなく、管理用ツールだけが厳選され、ローカルポリシーが「エージェントソフトのインストール禁止」と宣告しています。「デスクトップ体験」付きのバージョンであったとしても、変更管理委員会が申請を却下します。
プロトコルの道筋が、これらの機械をどう次々につなぐか
上記六つの機械は、設計であるにせよコンプライアンスであるにせよ、すでに受け付けている表示プロトコルまたはターミナルプロトコルを一つだけ聴いています。Citrix ホストは運用向けに RDP を解放し、VNC サーバーはイメージと一緒に配布されます。踏み台サーバーは SSH を通します。顧客のノートパソコンには、顧客の IT 部門が標準のリモート支援ツールで遠端支援への道筋をすでに開いています。キオスクのイメージには、運用者向けに RDP が最初から仕込まれています。ロックダウンされたサーバーはそもそも RDP、WinRM、SSH で管理されるものです。
DeskVNC の dvv 制御面は、この三つのプロトコルを直接喋ります。被制御側には何もインストールしません。クライアント側に新しいプロセスを持ち込むこともありません。人とエージェントが同じ一フレームの画面を見ているのは、構成上そうなるように作られているからです。リースのモデルはセッションごとに割り当てられ、いつでも取り消すことができます。オペレーターが被制御側でウィンドウをクリックした瞬間、エージェントから制御は人側へ戻り、その後の dvv_click は LEASE_REVOKED を返し、エージェントは直ちに停止すべきだと判断します。エージェントはオペレーターの操作を奪い返すのではなく、譲る側として最初から設計されています。誰の画面であるかが、いつも明確です。
これは README の次の一文を、エンジニアリングの言葉で展開したものです。
資金を集めた Windows デスクトップ用エージェントツールは、すべてそのデスクトップにエージェントをインストールします。Citrix でも、VDI でも、踏み台サーバーでも、顧客所有のマシンでも、それは拒まれます。しかし、その機械がすでに喋っているプロトコルは通るのです。
観察と実行のループ。実際の JSON、そのもの
dvv MCP サーバーは DeskVNC クライアントと同じプロセスで動作します。クライアントが遠端への接続を保持し、エージェントは「何を打ち、どこをクリックするか」だけを判断します。クリックには、直近のスクリーンから読み取った generation が常に付与されます。古くなった画面を根拠に計算されたクリックは、プロトコルの層に到達する前に拒否されます。これはエージェント側にも被制御側にも「思っていた場所と違う場所にクリックが届く」という事故を残しません。
dvv_hosts で開ける対象を列挙し、dvv_open に perceive: true を付ければ接続と画面と状態が一度に整い、dvv_control で排他的な入力リースを取得します。そこから先は、エージェントは安定した二呼び出しのループに入ります。見て、動く。もう一度見て、もう一度動く。最初の呼び出しが機械を開き、二つ目以降はそのループを保ったまま動作し続けます。
dvv_hosts {} // what there is to open
dvv_open {"hostId": "<id>", "perceive": true} // -> limbId, size, state
dvv_control {"limbId": "...", "action": "acquire"}
dvv_screen {"limbId": "...", "form": "full", "scale": 0.25}
dvv_click {"limbId": "...", "x": 700, "y": 400, "generation": 1}
dvv_screen {"limbId": "...", "form": "damage-crop"} // look again
dvv_type {"limbId": "...", "text": "notepad", "wpm": 3000}
dvv_key {"limbId": "...", "keys": "meta+r"}MCP ツールを持たないエージェントでも、dvv setup を一度実行すれば、シェルから等価な経路が使えます。
dvv hosts
dvv limbs
dvv open <name or hostId> --perceive
dvv wait <limbId> --until connected
dvv control acquire <limbId>
dvv screen <limbId> --scale 0.5 --out ./dvv-screen.png
dvv click <limbId> <x> <y>
dvv click <limbId> <x> <y> --action double
dvv type <limbId> "text to type"
dvv key <limbId> super+r
dvv wait <limbId> --until screen-stable
dvv reconnect <limbId>
dvv close <limbId>一台の機械はそれ自体が独立した limb であり、独立したリースを携えています。つまり十台の機械があれば、それは十本の互いに干渉しないループです。dvv_screen は imageSpace 行も出力し、縮小後の座標と機械の実座標との換算関係を明示します。スケールを誤ったクリックは、幾何不一致のチェックではじかれます。--scale 0.5 で見ているとき、画像の (mx, my) は機械の (mx2, my2) を意味します。エージェントはクリックの前に必ずこの換算を行い、換算を欠いたクリックは座標の不一致を理由に拒否されます。
generation は状態機械レベルの安全柵です。エージェントの内側ループは、見て、考えて、動くの三段です。この三段目の「動く」が、すでに存在しない世界に対して発動されれば、結果は深刻になります。generation は各フレームに付随する単調増加の整数で、次の入力には必ずこの値を添えて返さなければなりません。画面が前へ進んだ瞬間、古い generation を根拠にしたクリックは拒否され、エージェントはスクリーンを読み直し、現在の状況を反映した座標で再判断します。柵は追加の視覚モデルや計画モデルを必要とせず、二つの整数をすべての呼び出しに添えるだけで成立します。
測定された数字
以下の数字は、プロジェクトが公式に公開しているベンチマークを、1920x1080 の本物の Windows デスクトップ越しに、LAN 環境で測定したものです。
dvv_openと接続完了まで:4 msdvv_controlによるリース取得:1 ms 未満dvv_screen(scale: 0.25):25 ms- 一回の「観察してから実行する」サイクル:19 ms、およそ1 秒あたり 52 アクション
dvv_type(wpm: 12000時):447 文字/秒
19 ms という数字がわざわざ強調される理由は明白で、エージェントの外側ループ、つまり言語モデル呼び出しのコスト(低端で数百 ms、高端で秒単位)とは桁が違うからです。19 ms の内側ループであれば、モデルは二回の思考のあいだに数十回のアクションを挟めます。エージェントが画面を「待つ」必要はなく、人が低速な VNC を眺めながら待つような、あの待ち方とは無縁です。
比較を一つ添えると、通常の対話セッションで人がクリックしてから次の描画を見るまでの知覚上のラウンドトリップがあります。19 ms の内側ループは、その人参知のラウンドトリップより短い数字です。エージェントは人のふりをしているのではなく、人には回せないループを回しています。
dvv MCP サーバーをエージェントに登録する
DeskVNC クライアントの配布物には、dvv サーバー本体と、それを説明するスキル記述が同梱されています。リポジトリの skills/deskvnc/SKILL.md はエージェントがスキルディレクトリを走査する際に読む入口であり、エージェント側が自律的にこの能力を発見できる導線が最初から敷かれています。
これを一般的な MCP クライアントへ登録する手順は実質二段です。第一に、クライアントを操作する側の端末(Windows、macOS、Linux のいずれか)へインストールします。資格情報は OS のキーチェーンに預けられるので、初期状態で安全です。第二に、エージェント側の設定ファイルに dvv を MCP サーバーとして登録します。多くの場合は stdio 経由の一行設定で、実行ファイルのパスは OS ごとに次のようになります。Windows では %LOCALAPPDATA%\DeskVNCViewer\dvv.exe または C:\Program Files\DeskVNCViewer\dvv.exe、macOS では /Applications/DeskVNCViewer.app/Contents/MacOS/dvv、Linux では /usr/bin/dvv です。インストール直後から、エージェントは保存済みのホストを列挙し、選んで、開いて、回し始められます。
登録が完了すると、エージェント側には dvv_* のツール群が並んでいます。ホスト一覧、接続、リース、画面取得、クリック、文字入力、キー、クリップボード、ファイル、ターミナル読み書き、SSH でのコマンド実行、そして dvv_group_ で始まる複数台一括操作用のツールが揃っています。すべてはインストール直後から使えます。エージェント側に必要なのは接続先と権限の境界だけであり、被制御側に対する前提条件は何もありません。
エージェントがループ内で扱うべきエラーコードは二つだけです。LIMB_GONE は limb が失われたことを意味し、dvv_limbs で再列挙してから開き直します。SCREEN_CHANGED は画面が先に進んだことを意味し、もう一度スクリーンを読み直してから再試行します。どちらも回復可能なエラーであり、設計上「一旦止まって読み直す」ことだけが正しい応答です。エラーは失敗ではなく、合図です。
全体としての境界線
被制御側が新しいランタイムのインストールを拒むのはデフォルトです。しかし、インストールを拒むどの環境にも、その機械自身の運用者が普段使いで通している表示プロトコルかターミナルプロトコルが必ず残っています。セキュリティチームが信頼し、監査チームがすでに承認し、変更管理委員会がすでに通りにした道、それがプロトコルです。このプロトコルを喋るエージェントは、被制御側がはじめから開けてくれている扉を通ります。インストールを求めるエージェントは、セキュリティチームが何年もかけて縮めてきた面を、もう一度広げさせようとします。前者はスケールし、後者はしません。
DeskVNC クライアントは Rust と Tauri 2 で書かれたネイティブアプリで、Windows、macOS、Linux で動作し、MIT OR Apache-2.0 のデュアルライセンスで公開されています。dvv MCP サーバー、遠端には何も入れないこと、そして人がいつでも制御を取り戻せること。この三つが合わさった姿が、プロトコルの道筋のエンジニアリングのかたちです。
三つ目が重要です。人がいつでも制御を取り戻せるからこそ、はじめて自動化は「誰かのマシンで誰かが動かしている」という当たり前の事実の上に乗ります。エージェントは主役ではなく、客人です。客人は主人の画面を借りて動き、主人が戻ってきたら、席を譲る。それだけのことを、当たり前に、かつ高速にやる。それだけで、被制御側がインストールを拒む機械たちの多くは、もう「自動化できない機械」ではなくなります。
リポジトリは github.com/psmux/DeskVNC、日本語環境向けの追加の資料と更新は deskvnc-hub.pages.dev にあります。