Skip to main content
Glama

mcp-windows-debug

CI TypeScript License: MIT

TypeScript/Node.js MCPサーバーで、stdio経由でOpenCodeに接続し、モデルにWindowsマシン上の目と手を与えます。プロジェクトファイルの読み取り、スクリーンショットのキャプチャ、マウスの移動とキー入力、そして対象アプリケーションに対する自動デバッグループの実行を行います。

安全性こそが設計全体の要点です。独立したネイティブC++ウォッチドッグプロセスがグローバルな低レベルキーボード・マウスフックをインストールし、モデルが入力を注入している間でも、人間が常に保護されたアボートボタンをクリックできるようにします。Node MCPサーバーとウォッチドッグは2つの独立したプロセスであり、Nodeのイベントループが停止しても、入力がフリーズしたり、安全レイヤーが静かに失われたりすることはありません。すべてのアクションは、ガバナー、フレッシュネスチェック、ウィンドウスコープガードの3つのゲートを通過します。詳細は下記の「セキュリティモデル」セクションを参照してください。

これはWindows専用のv1です。macOSおよびLinuxバックエンドは、同じプロバイダーインターフェースの背後に後から組み込まれます。まだ実装されていません。

クイックスタート

git clone https://github.com/wgm66/mcp-windows-debug.git
cd mcp-windows-debug
npm install && npm run build
cd src\watchdog && build.bat   # build the C++ watchdog (MSVC required)
node dist\index.js --validate-config  # verify your OpenCode config

Related MCP server: Desktop Commander MCP Server

インストール

前提条件:

  • Node.js 20以上、およびnpm

  • Windows 10または11

  • 管理者アクセス(ウォッチドッグの実行にのみ必要。下記参照)

依存関係をインストールし、TypeScriptをビルドします:

npm install
npm run build

npm run build は tsc を実行し、OpenCodeが起動するエントリポイントである dist/index.js を生成します。

次に、ウォッチドッグをビルドします。これはMSVCでコンパイルされたC++ Win32コンソールアプリで、CMake、MSBuild、MinGWは一切使用しません:

cd src\watchdog
build.bat

build.bat にはVS2019ビルドツール(MSVC 14.29)とWindows SDKが必要です。ツールチェーンのパスはスクリプトにハードコードされているため、デフォルトのインストール場所にあることが前提です。出力は src\watchdog\watchdog.exe で、Nodeサーバーは実行時にプロジェクトルートからの相対パスでこれを特定します。

ウォッチドッグは昇格して実行する必要があります。グローバルな低レベルフックは、非昇格プロセスからのインストールを拒否します。これを満たす方法は2つあります:

  1. 昇格したターミナルからOpenCodeを起動し、生成されたウォッチドッグが昇格を継承するようにする。

  2. デバッグセッションを開始する前に、自分で管理者としてウォッチドッグを事前に起動する。

このビルドでは、サーバーは単独でUAC昇格を要求できません。昇格したウォッチドッグに到達できないデバッグセッションは ELEVATION_REQUIRED で失敗し、非昇格のウォッチドッグ実行は ERROR_ACCESS_DENIED を出力してコード1で終了します。黙って何もしないことはありません。

OpenCode設定

OpenCode設定(opencode.json)の mcp キーの下に windows-debug エントリを追加します。キーは mcpServers ではなく mcp である点に注意してください:

{
  "mcp": {
    "windows-debug": {
      "type": "local",
      "command": ["node", "<abs-path>/dist/index.js"],
      "environment": {}
    }
  }
}

<abs-path> をこのプロジェクトの絶対パスに置き換えます。JSONでエスケープが不要になるよう、フォワードスラッシュを使用してください。たとえば、プロジェクトが G:\工程开发\AI全场景图形化调试 にある場合、コマンドは次のようになります:

"command": ["node", "G:/工程开发/AI全场景图形化调试/dist/index.js"]

command はargvトークンの配列です。environment マップはデフォルトで空です。セッションごとのウォッチドッグトークンはサーバー自身が生成し、プロセス環境を介してウォッチドッグに渡されるため、ここで何かを設定する必要はありません。

使用方法

デバッグセッションの形は固定されています。保護されたアボートボタンを登録し、セッションを開始し、モデルに自動デバッグループを実行させ、セッションを終了します。

アボートボタンの登録。 セッションは保護領域がゼロの状態では開始できません。start_debug_session に regions({ x, y, w, h, id }、物理ピクセル)として1つ以上の画面矩形を渡します。登録された領域内を狙う注入入力はウォッチドッグによってブロックされます。人間の入力は常に通過するため、その領域はモデルが到達できない、保証された物理的なアボート領域です。領域はセッションの存続期間中、追記のみ可能です。開始後に領域を削除または移動する方法は、意図的に存在しません。

セッションの開始。 start_debug_session はウォッチドッグを起動またはアタッチし、すべての領域を登録し、ハートビートを開始します。オーケストレーターは現在のフォアグラウンドウィンドウをデバッグ対象として監視し始めます。sandbox: 'desktop' を渡すと、SendInput(実際のカーソルを動かす)の代わりに、プライベートなWin32デスクトップ(PostMessageベース、ユーザーの実際のマウス/キーボードには触れない)で注入を実行します。sandbox: 'rdp' は予約されていますが、v1では実装されていません。

自動デバッグループ。 セッションがアクティブな間、オーケストレーターは対象ウィンドウの変更(タイトル、矩形、フォアグラウンド状態、オプションでスクリーンショットシグネチャの差分)をポーリングします。トリガーが発火すると、新しいスクリーンショットをキャプチャし、debug://context リソースとして公開します。クライアント(OpenCode)は debug://context をポーリングし、何をするかを決定し、その決定を execute_action で呼び出します。オーケストレーターは自らアクションを決定することはありません。クライアントの決定を、ガバナー、フレッシュネス、安全性の各ゲートがすべて通過した後にのみ実行します。

セッションの終了。 end_debug_session はSHUTDOWNを送信し、ウォッチドッグが1秒以内に応答しない場合は強制終了し、保持されている修飾キーを解放し、IDLEに戻ります。MCPプロセスがクリーンシャットダウンなしで終了した場合、ウォッチドッグのデッドマンスイッチがフックを自ら解除します(「セキュリティモデル」セクションを参照)。

ツール

10個のツールが登録されています。

Tool

Purpose

read_file

絶対パスからテキストファイルを読み取ります。バイナリファイルはbase64を返します。

list_directory

ディレクトリの直下のエントリを一覧表示します。

capture_window

正確なタイトルでウィンドウをPNGとしてキャプチャします。空のタイトルは最前面のウィンドウを意味します。

mouse_click

論理画面座標を指定のボタンでクリックします。

mouse_move

カーソルを論理画面座標に移動します。

key_press

キーを押します。オプションで修飾キーを押しながら押します。

type_text

テキスト文字列をキーボード入力として入力します。

start_debug_session

ウォッチドッグを起動またはアタッチし、保護されたアボート領域を登録します。オプションの sandbox: 'desktop' で分離されたPostMessage注入を受け付けます。

end_debug_session

アクティブなセッションを終了し、ウォッチドッグをシャットダウンします。

execute_action

アクティブなセッション内でクライアントが決定したアクションを実行します。

inspect_element

UIAutomationツリーウォーカーで、可視のUI要素(名前、ロール、矩形、有効)を列挙します。

4つの入力ツール(mouse_click、mouse_move、key_press、type_text)はすべて、安全レイヤーの injectGuarded ゲートを経由します。アクティブなセッションなしで呼び出すと NO_ACTIVE_SESSION を返します。カーソルまたはキーボードフォーカスが対象ウィンドウの外にあるときに呼び出すと WINDOW_SCOPE_VIOLATION を返します。

リソース

3つのリソースが登録されています。

URI

Content

screenshot://full

プライマリモニタのPNGキャプチャ。

screenshot://monitor/{index}

0ベースのインデックスで指定したモニタのPNGキャプチャ。

debug://context

自動デバッグループのJSONスナップショット: ステータス、ターゲット、トリガー、スクリーンショット、ガバナー状態。

ガバナー制限

オーケストレーターは介入に固定のスロットルを適用します:

  • アクション間の5秒のクールダウン

  • 1分あたり6回の介入

  • 3回連続失敗後の自動一時停止

  • 30分のハードなセッション上限。これを超えるとセッションは自動終了

クールダウン、レート制限、または一時停止による拒否はスロットリングであり、失敗ではありません。3回失敗の一時停止にカウントされるのは、失効状態の拒否または注入エラーのみです。

セキュリティモデル

この設計が保証することと、保証しないこと。

デュアルプロセス分離。 Node MCPサーバーとネイティブウォッチドッグは別々のプロセスです。ウォッチドッグは独自のメッセージループを実行するため、Nodeのイベントループが停止しても、フックをブロックしたり、安全レイヤーを失ったりすることはありません。

デッドマンスイッチ。 ウォッチドッグは名前付きパイプをリッスンし、任意のバイトをハートビートとして扱います。2秒以上ハートビートが届かない場合、両方のフックで UnhookWindowsHookEx を呼び出し、クリーンに終了します。解除の猶予期間と合わせて、MCPの終了から3秒以内にフックが解除されるため、クラッシュまたは強制終了したサーバーが入力ブロックを残すことはありません。これはフェイルセーフの契約であり、サブ秒の保証ではありません。

ウィンドウスコープ。 セッションがアクティブで、カーソルとキーボードフォーカスがセッションの対象ウィンドウ内にある場合を除き、すべての注入は拒否されます。

セキュアデスクトップの処理。 OSがセキュアデスクトップ(UACプロンプトまたはロック画面)に切り替わった場合、オーケストレーターは一時停止し、入力を一切試行せずに注入を拒否します。

追記専用の監査。 すべてのファイル読み取り、注入アクション、スクリーンショット要求、介入決定は、追記専用の監査ログに記録されます。キーストロークの内容とファイルの内容がログに書き込まれることはありません。

保証されないこと。 この部分は注意深く読んでください。これらが正直な残余リスクです。

  • 注入入力のフィルタリングは絶対的なブロックではありません。 ウォッチドッグは、宛先が保護領域内にある場合、LLKHF_INJECTED / LLMHF_INJECTED フラグを持つ入力をブロックします。これにより、SendInput が生成するマシン注入入力を停止します。ただし、すべての可能な入力ソースを停止するわけではありません。別のプロセスが他の手段で非フラグの入力を合成する可能性があり、その入力はフィルタを通過します。このツールは絶対的な物理的ブロックを主張するものではありません。アボートボタンは、数学的な保証ではなく、強力なベストエフォートの安全ネットとして扱ってください。

  • 最悪の場合はリモートコントロールのプリミティブです。 ツールの完全な表面は、ファイル読み取り、スクリーンショットキャプチャ、キーボード・マウス注入です。攻撃者や誤動作するモデルがこれを制御した場合、それが彼らが得る能力です。その表面が向けられても構わないマシンとウィンドウに対してのみ使用してください。

  • アンチウイルスとEDRがフラグを立てる可能性があります。 グローバルな低レベルフックと SendInput 注入は、リモートアクセスツールやキーロガーが使用するまさにその手法です。AV/EDR製品からの誤検出を想定してください。ウォッチドッグが隔離されたり、セッション中に強制終了されたりする可能性も含みます。デッドマンスイッチにより安全ですが(フックは解除されます)、セッションは中断されます。「トラブルシューティング」を参照してください。

  • 昇格は攻撃面を広げます。 ウォッチドッグはグローバルフックをインストールするために管理者権限を必要とするため、セッションは昇格したプロセスが存在する状態で実行されます。その露出が許容できないマシンでは実行しないでください。

ウォッチドッグがキーストロークやボタンの内容を読み取ったりログしたりすることはありません。検査されるのは注入フラグとカーソルの宛先のみです。トランスポートはローカルの名前付きパイプのみです。TCP、ネットワークリスナー、リモートコントロールは一切ありません。

トラブルシューティング

ウイルス対策ソフトまたはEDRがウォッチドッグを検出する。 AV/EDRコンソールでsrc\watchdog\watchdog.exe(またはプロジェクトディレクトリ)の除外を追加してください。恒久的な修正はコード署名です。署名付きバイナリは隔離される可能性がはるかに低くなります。ウォッチドッグがセッション中に強制終了された場合、セッションはIDLEに遷移し、新しいstart_debug_sessionが開始されるまで、すべての入力ツールが拒否されます。

Windowsがフックを切り離す(LowLevelHooksTimeout)。 低レベルフックプロシージャには、HKCU\Control Panel\Desktop\LowLevelHooksTimeout(デフォルト300 ms)で制御される厳格な実行予算があります。フックプロシージャが長く実行されすぎると、Windowsはそれを静かに削除します。ウォッチドッグはフックプロシージャを100 ms未満に保つため、通常の使用ではこれは発生しません。負荷の高いマシンでフックがドロップする場合、問題はシステム負荷または別の低レベルフックからの干渉であり、このツールではありません。

マルチモニターまたは混合DPI環境でクリックが誤った場所に着地する。 座標は、モニターごとのDPIを使用して論理ピクセルと物理ピクセルの間でマッピングされます。混合DPIのマルチモニター環境には既知の制限があります。論理から物理への変換が、物理ピクセルを期待する呼び出しに論理座標を渡します。96 DPIでは無害ですが、スケーリングされたモニターではずれる可能性があります。クリックが外れた場合は、まずスクリーンショットを撮り、そこからターゲット座標を読み取り、プライマリモニターでの作業を優先してください。

UACプロンプトが表示される、またはインジェクションが静かに失敗する。 ウォッチドッグは昇格して実行されるため、起動するとUACプロンプトが表示されることがあります。キャンセルすると、セッションはELEVATION_REQUIREDで失敗します。このビルドではサーバーは単独で昇格を再要求できないため、セッションを開始する前にウォッチドッグを管理者として事前に起動するか、昇格したターミナルからOpenCodeを起動してください。

ウォッチドッグを手動で実行するとERROR_ACCESS_DENIEDが発生する。 これは非昇格シェルでの期待される動作です。ウォッチドッグは管理者なしでは実行を拒否し、終了コード1でERROR_ACCESS_DENIEDを出力するため、静かなno-opはありません。代わりに昇格したPowerShellから実行してください。

セッション記録

セッションは、後で再生するためのJSONトランスクリプトとして記録できます。レコーダーは監査ログにフックし、キーストロークコンテンツなしで(データ最小化)すべてのツール呼び出し(名前、引数、結果、タイムスタンプ)をキャプチャします。トランスクリプトは.omo/recordings/session-<id>.jsonに保存されます。

# A session transcript can be replayed programmatically:
node -e "const { SessionRecorder } = require('./dist/recording'); SessionRecorder.replay('.omo/recordings/session-xxx.json', async (call) => { console.log(call.toolName, call.args); })"

UIAutomation(アクセシビリティAPI)

inspect_elementツールは、UIAutomationツリーウォーカーを介して表示されているUI要素を列挙します(terminator-mcp-agentおよびWindows MCP Inspectorとの競合他社同等性)。v1では、これは注入されたdepsシームから要素を返すスタブです。完全なCOM相互運用にはネイティブN-APIアドオンが必要です(将来の作業)。UIAutomationProviderクラスはInputProviderを実装しますが、v1ではインジェクションメソッドに対してUIAutomationErrorをスローします。実際のインジェクションにはSendInputまたはPostMessageパスを使用してください。

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    F
    maintenance
    A standalone MCP server for Windows desktop control, enabling screenshots, mouse and keyboard input, app launch, window/display management, and clipboard access via natural language.
    3
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server that gives AI agents human-like control over Windows via visual perception and simulated mouse and keyboard input, enabling automation of any application without APIs.
    19 npm
    3
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A local, dependency-free MCP server that gives AI agents controlled access to the active Windows desktop, enabling automated interaction with applications through screenshots, clicks, typing, and window management.
    75 npm
    MIT