Skip to main content
Glama

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の authToken Cookieを設定します。

  • ローカルWebRTC signalingは認証保護された GET /webrtc/signaling/client を使います。

  • UIは RTCPeerConnectionrecvonly video 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更新後は入力系の互換性を再検証してください。

主要コンポーネント:

ファイル

責務

設計理由

server.ts

MCP schemaとstdio lifecycle

Playwrightや資格情報をMCP境界へ露出させない

session.ts

Browser/WebRTC常駐、直列化、再接続

競合を避け、全Toolで同一DataChannelを使う

capture.ts

受信映像の元のピクセル寸法でframe取得、障害診断

JetKVM UI全体ではなくPC1映像だけを扱う

input.ts

公式HID hook・wheel RPCへのdispatch

PC2ブラウザ操作ではなくPC1へ確実に届ける

keyboard.ts

MCP key名、KeyboardEvent.code、USB HIDの対応

キー変換と送信処理を分離する

unlock.ts

OCR三値判定と最大1回の認証

誤判定時の通常アプリへの秘密入力を防ぐ

Tool呼び出しのFLOW:

MCP client
  → Zod引数検証
  → JetKvmSession内の直列実行キュー
  → WebRTC video健全性確認
  → 映像取得、または公式UIのHID/RPC経路
  → MCP response

WebRTC切断時は同じpageを1回だけreloadして再接続します。30秒以内に復旧しない場合は診断ファイルを保存し、別のJetKVM WebRTCセッションが存在する可能性を含むエラーを返します。

JetKVMは同時WebRTCセッションが競合する場合があります。MCP Server利用中は、通常のChrome/Safari等で同じJetKVM KVM画面を開かないでください。

公式資料:

セットアップ

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 chromium

JETKVM_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#roottext=JetKVM の要素数

  • screenshots/debug-page.html

  • screenshots/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

引数

動作

take_screenshot

filename?: string

受信映像と同じピクセル寸法のPNGを保存・返却

move_mouse

x: int, y: int

PC1映像座標へ絶対移動

click

x, y, button?: left|right|middle

指定位置を1回クリック

double_click

x: int, y: int

左button down/upを2組送信

scroll

dx: number, dy: number

公式UIのwheel listener経由でスクロールRPCを送信

press_key

key: string

対応キーをdown/up

hotkey

keys: string[]

順にdown、逆順にup。META/CMD対応

type_text

text: string

printable ASCIIをUS配列として入力

unlock_pc

なし

明確なロック画面だけ認証を最大1回試行

ensure_unlocked

なし

解除済みなら無入力、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.pngensure-unlocked-before.png、結果確認は unlock-after.png として screenshots/ 内だけに保存します。

戻り値の statusunlockedalready_unlockednot_lock_screenstate_unknownunlock_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_screenshot 3回、move_mouse 2回を実行。

  • (100,100) → HID (1708,3037)(1700,900) → HID (29028,27331)

  • 両方とも公式E2E HID hook、HID ready、RPC DataChannel open、WebRTC connectedを確認。

  • mouse-a.pngmouse-b.png でPC1カーソルが異なる2地点へ移動したことを確認。

  • click、double_click、scroll、press_key、hotkey、type_textの実機呼び出しは0回。

  • 2026-08-18 STEP 2: 同一WebRTCセッションで take_screenshot 2回、move_mouse 1回、left click 1回を実行。

  • (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_screenshot 2回、press_key("Tab") 1回(down/up各1回)を実行。

  • Tabは公式 sendKeypress E2E HID hook(USB HID usage 0x2b)経由。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_screenshot 3回、type_text("abc") 1回、press_key("Backspace") 3回を実行。

  • abc とBackspaceは公式 sendKeypress E2E HID hook経由。HID ready、RPC DataChannel open、WebRTC connectedを全入力で確認。小文字入力のためShiftは0回、Enterは0回。

  • 入力後はパスワード欄に3文字分のマーカーが表示され、Backspace 3回後にすべて消えた。ロック画面からの遷移および追加操作はなし。

  • 2026-08-18 STEP 5: 同一WebRTCセッションで take_screenshot 2回、move_mouse(1400,700) 1回、left double_click(1400,700) 1回を実行。

  • double-clickは公式 sendAbsMouseMove E2E HID hook経由でleft button down/upを各2回送信。HID ready、RPC DataChannel open、WebRTC connectedを確認。

  • ロック画面の何もない場所で実施し、画面状態の変更なし。単発clickおよびその他の追加入力は0回。

  • 2026-08-18 STEP 6: 同一WebRTCセッションで take_screenshot 2回、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回、画面変化なし。

  • TAB aliasを Tab に正規化する修正とunit testを追加済み。安全条件に従い、この回では実機再試行を行っていない。

  • 2026-08-18 STEP 7再試行: 同一WebRTCセッションで take_screenshot 2回、hotkey(["SHIFT","TAB"]) 1回を実行。

  • 公式 sendKeypress E2E HID hookからShiftLeft down (0xe1)、Tab down (0x2b)、Tab up、ShiftLeft upの順に送信。HID ready、RPC DataChannel open、WebRTC connectedを確認。

  • PC1は壁紙のみの表示からロック画面表示へ変化。その他の入力Toolと追加実機入力は0回。

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

  • A
    license
    -
    quality
    D
    maintenance
    Enables 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.
    1
    MIT
  • A
    license
    A
    quality
    -
    maintenance
    Enables 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.
    14
    23
    7,623
    5
  • A
    license
    -
    quality
    D
    maintenance
    Enables AI to control a computer through mouse, keyboard, and screen capture tools, with support for local native and Docker sandboxed environments.
    11
    5
    MIT
  • A
    license
    C
    quality
    B
    maintenance
    Exposes 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.
    40
    22
    8
    Apache 2.0

View all related MCP servers

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.

View all MCP Connectors

Latest Blog Posts

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