JetKVM MCP Server
JetKVM MCP Server
JetKVMの公式ローカルWeb UIをPlaywrightで開き、接続先コンピューターの画面取得とHID入力をMCP Toolとして提供するstdioサーバーです。
この文書では、JetKVMに接続されて操作を受けるコンピューターを「PC1」、MCP ServerとPlaywrightを実行するコンピューターを「PC2」と呼びます。HIDは、JetKVMがPC1へ送るマウス・キーボード入力を指します。
実装済み機能
PC1から受信した映像フレームと同じピクセル寸法でのPNG取得
絶対マウス移動、クリック、ダブルクリック、スクロール
単一キー、macOS向けhotkey、printable ASCII入力
複数の画面特徴を必要とするmacOSロック画面判定と、最大1回に制限したロック解除試行
BrowserContext・WebRTC・HID DataChannelの常駐再利用
WebRTC切断時の1回限定再接続と、HTML/PNG診断保存
出力先制限、ディレクトリ外を指すファイル名の拒否、資格情報のログ抑止
Related MCP server: Playwright MCP
調査に基づく方式
2026-08-18時点のJetKVM公式 jetkvm/kvm リポジトリ(dev、commit b3c29a44d9e2862b8ff7530830781803ce27b060)を確認しました。
ローカル認証UIは
POST /auth/login-localを使い、成功時にHttpOnlyのauthTokenCookieを設定します。ローカルWebRTC signalingは認証保護された
GET /webrtc/signaling/clientを使います。UIは
RTCPeerConnectionにrecvonlyvideo transceiverを追加し、受信MediaStreamを<video>のsrcObjectに設定します。本実装はこの公式UIをそのままPlaywrightで実行し、デコード済みvideo frameをcanvasへ描画してPNG化します。
独自signaling、Developer Mode、独自Firmware、Cloud/Remote Access、JetKVM設定変更は使いません。仮想メディア、Wake on LAN、Terminal、Serial等も公開しません。
アーキテクチャ
MCP Server起動時にPlaywright Chromium、BrowserContext、pageを各1つだけ作成し、JetKVMへ一度ログインしてWebRTC videoがreadyになるまで待機します。全Toolは同じpageとWebRTC/DataChannelセッションを共有し、同時呼び出しは順番に処理します。通常のTool呼び出しでブラウザ再起動や再ログインは行いません。
入力にはPlaywrightの page.mouse / page.keyboard を使いません。これらはPC2上のChromiumを操作するだけで、PC1へ届くことを保証できないためです。
マウスとキーボードは、JetKVM公式Web UIがE2Eテスト用に公開している window.__kvmTestHooks を優先して呼び出します。hookが利用できない場合は、公式UIが <video> と document に登録したイベントlistenerへDOMイベントを送ります。スクロールは常に公式UIのvideo用wheel listenerを経由します。この設計により、独自のHIDパケットを実装せず、公式UI内のHID RPC handshake、DataChannel選択、旧バージョン向けfallbackを再利用します。
__kvmTestHooks はJetKVMの安定した外部APIではありません。本実装は上記commitで実装を確認しているため、JetKVM更新後は入力系の互換性を再検証してください。
主要コンポーネント:
ファイル | 責務 | 設計理由 |
| MCP schemaとstdio lifecycle | Playwrightや資格情報をMCP境界へ露出させない |
| Browser/WebRTC常駐、直列化、再接続 | 競合を避け、全Toolで同一DataChannelを使う |
| 受信映像の元のピクセル寸法でframe取得、障害診断 | JetKVM UI全体ではなくPC1映像だけを扱う |
| 公式HID hook・wheel RPCへのdispatch | PC2ブラウザ操作ではなくPC1へ確実に届ける |
| MCP key名、KeyboardEvent.code、USB HIDの対応 | キー変換と送信処理を分離する |
| OCR三値判定と最大1回の認証 | 誤判定時の通常アプリへの秘密入力を防ぐ |
Tool呼び出しのFLOW:
MCP client
→ Zod引数検証
→ JetKvmSession内の直列実行キュー
→ WebRTC video健全性確認
→ 映像取得、または公式UIのHID/RPC経路
→ MCP responseWebRTC切断時は同じpageを1回だけreloadして再接続します。30秒以内に復旧しない場合は診断ファイルを保存し、別のJetKVM WebRTCセッションが存在する可能性を含むエラーを返します。
JetKVMは同時WebRTCセッションが競合する場合があります。MCP Server利用中は、通常のChrome/Safari等で同じJetKVM KVM画面を開かないでください。
公式資料:
https://github.com/jetkvm/kvm/blob/dev/ui/src/routes/login-local.tsx
https://github.com/jetkvm/kvm/blob/dev/ui/src/routes/devices.%24id.tsx
https://github.com/jetkvm/kvm/blob/dev/ui/src/components/WebRTCVideo.tsx
セットアップ
Node.js 20以上が必要です。
npm install
npx playwright install chromium
export JETKVM_URL=http://jetkvm.local
export JETKVM_PASSWORD='your-local-password'
export JETKVM_SCREENSHOT_DIR=./screenshots
export JETKVM_PC_PASSWORD='your-pc1-macos-password'
npm run build.envを使う場合、サーバー自身はdotenvを自動読込みしないため、起動シェルで読み込ませます。
cp .env.example .env
# .envへ実値を設定(Gitにはcommitしない)
set -a
source .env
set +a
npm run build
npm start初回のみChromiumを導入します。依存関係を更新しない通常起動では再実行不要です。
npx playwright install chromiumJETKVM_PC_PASSWORD はPC1 macOSのロック解除専用です。Tool引数には渡さず、PC2上のローカルな .env だけで管理してください。.env はgitignore済みですが、誤って別名で複製しないでください。Hermes等の設定ファイルへ平文で記載せず、起動シェルから環境変数を継承する運用を推奨します。
PNG取得の直接検証
npm run screenshot -- current-screen.png成功時は screenshots/current-screen.png を保存します。ファイル名は JETKVM_SCREENSHOT_DIR の外へ出られず、.png のみ許可します。
各実行ではSPA初期化のため5秒待機した後、video待機より先に次の診断情報も保存・stderr表示します。videoが取得できない場合も診断ファイルは残ります。
現在URL、ページタイトル、本文先頭2000文字
video、password input、form、#root、text=JetKVMの要素数screenshots/debug-page.htmlscreenshots/debug-page.png(full-page)
MCP設定例
{
"mcpServers": {
"jetkvm": {
"command": "node",
"args": ["/path/to/jetkvm-mcp/dist/server.js"],
"env": {
"JETKVM_URL": "http://jetkvm.local",
"JETKVM_PASSWORD": "<local-password>",
"JETKVM_SCREENSHOT_DIR": "/path/to/jetkvm-mcp/screenshots"
}
}
}
}公開ToolとMCP引数:
Tool | 引数 | 動作 |
|
| 受信映像と同じピクセル寸法のPNGを保存・返却 |
|
| PC1映像座標へ絶対移動 |
|
| 指定位置を1回クリック |
|
| 左button down/upを2組送信 |
|
| 公式UIのwheel listener経由でスクロールRPCを送信 |
|
| 対応キーをdown/up |
|
| 順にdown、逆順にup。 |
|
| printable ASCIIをUS配列として入力 |
| なし | 明確なロック画面だけ認証を最大1回試行 |
| なし | 解除済みなら無入力、lockedだけ共通解除処理 |
スクリーンショットの書込み先は、サーバープロセスのカレントディレクトリ直下にある screenshots/ のみに制限されます。JETKVM_SCREENSHOT_DIRを指定する場合も、正規化後にこの場所と一致する必要があります。../や絶対パスなど、このディレクトリ外を指すファイル名は拒否します。
PC1ロック解除の安全仕様
ロック状態はPC1映像をPC2上のTesseract.js(WASM、英語・日本語データ同梱)で領域別OCRし、locked / unlocked / unknown の三値で判定します。画像やOCR結果を外部サービスへ送信しません。
OCR実装: https://github.com/naptha/tesseract.js
locked: 所定領域で時刻、日付、パスワード案内の3種類をすべて確認unlocked: パスワード案内がなく、画面上端で既知のmacOSメニューバー語を3種類以上確認unknown: 上記の証拠が揃わない状態。パスワードもEnterも送信しない
これはmacOSの状態をOS APIから取得する方式ではなく、画面上の文字配置に基づく保守的な判定です。表示言語、解像度、壁紙、macOSのUI変更によって unknown になる可能性があります。誤入力を避けるため、証拠不足時にロック解除を試みないことを優先します。
unlock_pc() と ensure_unlocked() はMCP引数を取りません。資格情報は JETKVM_PC_PASSWORD からのみ読み、ログ、例外、MCP response、ファイル名へ含めません。資格情報入力は診断ログを出さない専用の内部HID経路を使います。1回のTool呼び出しにつきパスワード入力とEnterは最大1回で、自動リトライは行いません。判定用画像は unlock-before.png、ensure-unlocked-before.png、結果確認は unlock-after.png として screenshots/ 内だけに保存します。
戻り値の status は unlocked、already_unlocked、not_lock_screen、state_unknown、unlock_failed のいずれかです。
テスト
npm test
npm run buildロードマップ
今後の候補:
OCR workerのセッション内再利用による状態判定レイテンシ短縮
macOSの表示言語・解像度・壁紙バリエーションを増やしたlock判定fixture
入力Toolごとの構造化監査イベント(秘密情報を含めない)
WebRTC/DataChannelの状態を入力なしで確認するread-only health Tool
Hermes Agent向けの秘密情報を設定ファイルへ直書きしない起動wrapper
明示的な非目標:
Developer Mode、独自Firmware、Cloud/Remote Accessの利用
JetKVM設定変更API、Terminal、Serial、仮想メディア、Wake on LANの公開
日本語IMEへの直接文字列注入、認証失敗時の自動リトライ
実機検証ログ
2026-08-18 STEP 1: 同一WebRTCセッションで
take_screenshot3回、move_mouse2回を実行。(100,100)→ HID(1708,3037)、(1700,900)→ HID(29028,27331)。両方とも公式E2E HID hook、HID ready、RPC DataChannel open、WebRTC connectedを確認。
mouse-a.pngとmouse-b.pngでPC1カーソルが異なる2地点へ移動したことを確認。click、double_click、scroll、press_key、hotkey、type_textの実機呼び出しは0回。
2026-08-18 STEP 2: 同一WebRTCセッションで
take_screenshot2回、move_mouse1回、leftclick1回を実行。(960,540)→ HID(16392,16399)。move/clickとも公式E2E HID hook、HID ready、RPC DataChannel open、WebRTC connectedを確認。安全なロック画面背景をクリックしたため、カーソル移動以外のPC1 UI変化はなし。
double_click、right click、scroll、press_key、hotkey、type_textのSTEP 2実機呼び出しは0回。
2026-08-18 STEP 3: 同一WebRTCセッションで
take_screenshot2回、press_key("Tab")1回(down/up各1回)を実行。Tabは公式
sendKeypressE2E HID hook(USB HID usage0x2b)経由。HID ready、RPC DataChannel open、WebRTC connectedを確認。before/after画像ではロック画面の明確なフォーカス変化を判定できなかった。Tab以外のキー、click、double_click、scroll、hotkey、type_textのSTEP 3実機呼び出しは0回。
2026-08-18 STEP 4: 同一WebRTCセッションで
take_screenshot3回、type_text("abc")1回、press_key("Backspace")3回を実行。abcとBackspaceは公式sendKeypressE2E HID hook経由。HID ready、RPC DataChannel open、WebRTC connectedを全入力で確認。小文字入力のためShiftは0回、Enterは0回。入力後はパスワード欄に3文字分のマーカーが表示され、Backspace 3回後にすべて消えた。ロック画面からの遷移および追加操作はなし。
2026-08-18 STEP 5: 同一WebRTCセッションで
take_screenshot2回、move_mouse(1400,700)1回、leftdouble_click(1400,700)1回を実行。double-clickは公式
sendAbsMouseMoveE2E HID hook経由でleft button down/upを各2回送信。HID ready、RPC DataChannel open、WebRTC connectedを確認。ロック画面の何もない場所で実施し、画面状態の変更なし。単発clickおよびその他の追加入力は0回。
2026-08-18 STEP 6: 同一WebRTCセッションで
take_screenshot2回、Slackメッセージ本文領域へのmove_mouse(1150,540)1回、scroll(0,500)1回を実行。scrollは公式video wheel listenerからJetKVMのwheel RPC経路へ送信され、正規化wheel値は
(0,-5)。HID ready、RPC DataChannel open、WebRTC connectedを確認。before/afterでSlackメッセージ本文が上方向へ移動したことを確認。click、double_click、keyboard系Toolおよびその他の追加入力は0回。
2026-08-18 STEP 7初回:
hotkey(["SHIFT","TAB"])は大文字TABの正規化エラーでHID dispatch前に停止。スクリーンショット2回、PC1へのHID入力0回、画面変化なし。TABaliasをTabに正規化する修正とunit testを追加済み。安全条件に従い、この回では実機再試行を行っていない。2026-08-18 STEP 7再試行: 同一WebRTCセッションで
take_screenshot2回、hotkey(["SHIFT","TAB"])1回を実行。公式
sendKeypressE2E HID hookからShiftLeft down (0xe1)、Tab down (0x2b)、Tab up、ShiftLeft upの順に送信。HID ready、RPC DataChannel open、WebRTC connectedを確認。PC1は壁紙のみの表示からロック画面表示へ変化。その他の入力Toolと追加実機入力は0回。
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceEnables browser automation through Playwright with persistent sessions and cookie state management. Supports web navigation, page interaction, and browser control via JSON-RPC protocol over stdin/stdout.1MIT
- AlicenseAquality-maintenanceEnables browser automation through Playwright using accessibility tree snapshots instead of screenshots. Supports web scraping, form interactions, testing, and connecting to existing browser sessions with logged-in accounts.14237,6235
- Alicense-qualityDmaintenanceEnables AI to control a computer through mouse, keyboard, and screen capture tools, with support for local native and Docker sandboxed environments.115MIT
- AlicenseCqualityBmaintenanceExposes a remote browser as MCP tools via Playwright, enabling AI agents to navigate and interact with web pages through DOM snapshots, clicks, typing, and form operations.40228Apache 2.0
Related MCP Connectors
Eyes and hands on real Windows PCs — observe, click, type via Glasswarp API.
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
AI-powered browser automation — navigate, click, fill forms, and extract data from any website.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/YokihitoOkiBiz/jetkvm-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server