JetKVM MCP Server
JetKVM MCP Server
Это stdio-сервер, который открывает официальный локальный веб-интерфейс JetKVM через Playwright и предоставляет захват экрана подключенного компьютера и HID-ввод в качестве MCP Tool.
В этом документе компьютер, подключенный к JetKVM и управляемый им, называется «ПК1», а компьютер, на котором выполняются MCP Server и Playwright, — «ПК2». HID относится к вводу мыши и клавиатуры, которые JetKVM отправляет на ПК1.
Реализованные функции
Получение PNG с теми же размерами в пикселях, что и видеокадр, полученный от ПК1
Абсолютное перемещение мыши, щелчок, двойной щелчок, прокрутка
Ввод одиночной клавиши, горячих клавиш для macOS, печатных ASCII-символов
Определение экрана блокировки macOS, требующего нескольких визуальных признаков, и попытка разблокировки, ограниченная максимум одним разом
Постоянное повторное использование BrowserContext, WebRTC и HID DataChannel
Однократное повторное подключение при разрыве WebRTC и сохранение диагностики в HTML/PNG
Ограничение выходного каталога, отклонение имен файлов, указывающих за его пределы, подавление учетных данных в журналах
Related MCP server: Playwright MCP
Метод, основанный на исследовании
Был проверен официальный репозиторий JetKVM jetkvm/kvm (ветка dev, коммит b3c29a44d9e2862b8ff7530830781803ce27b060) по состоянию на 2026-08-18.
Локальный интерфейс аутентификации использует
POST /auth/login-localи при успехе устанавливает HttpOnly cookieauthToken.Локальный WebRTC signaling использует защищенный аутентификацией
GET /webrtc/signaling/client.Интерфейс добавляет
recvonlyвидеотрансивер кRTCPeerConnectionи устанавливает полученный MediaStream какsrcObjectдля<video>.Данная реализация просто запускает этот официальный интерфейс через Playwright, рисует декодированный видеокадр на canvas и преобразует его в PNG.
Собственный signaling, Developer Mode, собственная прошивка, Cloud/Remote Access и изменение настроек JetKVM не используются. Виртуальные носители, Wake on LAN, Terminal, Serial и т. д. также не предоставляются.
Архитектура
При запуске MCP Server создается по одному экземпляру Playwright Chromium, BrowserContext и page, выполняется однократный вход в JetKVM и ожидание готовности WebRTC-видео. Все инструменты используют один и тот же page и сеанс WebRTC/DataChannel; одновременные вызовы обрабатываются последовательно. Обычные вызовы инструментов не вызывают перезапуск браузера или повторный вход.
Для ввода не используются page.mouse / page.keyboard из Playwright, так как они управляют только Chromium на ПК2 и не гарантируют доставку на ПК1.
Для мыши и клавиатуры в первую очередь вызывается window.__kvmTestHooks, который официальный веб-интерфейс JetKVM предоставляет для E2E-тестирования. Если hook недоступен, DOM-события отправляются слушателям событий, зарегистрированным официальным интерфейсом на <video> и document. Прокрутка всегда осуществляется через wheel-слушатель официального интерфейса, предназначенный для видео. Такая конструкция позволяет повторно использовать handshake HID RPC, выбор DataChannel и fallback для старых версий из официального интерфейса, не реализуя собственные HID-пакеты.
__kvmTestHooks не является стабильным внешним API JetKVM. Поскольку данная реализация проверена на указанном коммите, после обновления JetKVM необходимо повторно проверить совместимость системы ввода.
Основные компоненты:
Файл | Обязанность | Причина разработки |
| Схема MCP и stdio lifecycle | Не допускать Playwright и учетные данные к границе MCP |
| Постоянное использование Browser/WebRTC, сериализация, переподключение | Избежать конфликтов, использовать один DataChannel для всех инструментов |
| Получение кадра с исходными размерами пикселей, диагностика ошибок | Обрабатывать только видео с ПК1, а не весь интерфейс JetKVM |
| Диспетчеризация к официальному HID hook и wheel RPC | Гарантированная доставка на ПК1, а не управление браузером ПК2 |
| Соответствие имен клавиш MCP, KeyboardEvent.code и USB HID | Разделение преобразования клавиш и отправки |
| Троичное определение OCR и максимум одна аутентификация | Предотвращение ввода секретов в обычные приложения при ошибочном определении |
ПОТОК вызова инструмента:
MCP client
→ Zod引数検証
→ JetKvmSession内の直列実行キュー
→ WebRTC video健全性確認
→ 映像取得、または公式UIのHID/RPC経路
→ MCP responseПри разрыве WebRTC та же страница перезагружается один раз для повторного подключения. Если восстановление не происходит в течение 30 секунд, сохраняются диагностические файлы и возвращается ошибка, включающая возможность существования другого сеанса WebRTC JetKVM.
JetKVM может конфликтовать при одновременных сеансах WebRTC. Во время использования MCP Server не открывайте экран KVM того же JetKVM в обычном Chrome/Safari и т. д.
Официальные материалы:
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 предназначен только для разблокировки ПК1 (macOS). Не передавайте его в аргументах инструмента, управляйте им только через локальный .env на ПК2. .env уже добавлен в gitignore, но не копируйте его случайно под другим именем. Рекомендуется не записывать его в открытом виде в файлы конфигурации, такие как Hermes, а наследовать переменные окружения из оболочки запуска.
Прямая проверка получения PNG
npm run screenshot -- current-screen.pngПри успехе сохраняется screenshots/current-screen.png. Имя файла не может выходить за пределы JETKVM_SCREENSHOT_DIR, разрешено только расширение .png.
При каждом выполнении после 5-секундного ожидания инициализации SPA, до ожидания видео, также сохраняется и выводится в stderr следующая диагностическая информация. Если видео не получено, диагностические файлы все равно сохраняются.
Текущий URL, заголовок страницы, первые 2000 символов текста
Количество элементов
video, password input,form,#root,text=JetKVMscreenshots/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"
}
}
}
}Предоставляемые инструменты и аргументы MCP:
Инструмент | Аргументы | Действие |
|
| Сохраняет и возвращает PNG с теми же размерами в пикселях, что и полученное видео |
|
| Абсолютное перемещение в координаты видео ПК1 |
|
| Один щелчок в указанной позиции |
|
| Отправляет две пары нажатий/отпусканий левой кнопки |
|
| Отправляет RPC прокрутки через wheel-слушатель официального интерфейса |
|
| Нажатие/отпускание соответствующей клавиши |
|
| Нажатие по порядку, отпускание в обратном порядке. Поддержка |
|
| Ввод печатных ASCII-символов в раскладке US |
| Нет | Попытка аутентификации только при явном экране блокировки, максимум один раз |
| Нет | Если разблокирован — без ввода, если заблокирован — общая обработка разблокировки |
Запись скриншотов ограничена каталогом screenshots/, находящимся непосредственно в текущем каталоге серверного процесса. При указании JETKVM_SCREENSHOT_DIR он также должен совпадать с этим местоположением после нормализации. Имена файлов, указывающие за пределы этого каталога, такие как ../ или абсолютные пути, отклоняются.
Спецификация безопасности разблокировки ПК1
Состояние блокировки определяется путем OCR по областям видео ПК1 с помощью Tesseract.js (WASM, включает английские и японские языковые данные) на ПК2 и выносится троичное решение: locked / unlocked / unknown. Изображения и результаты OCR не отправляются внешним сервисам.
Реализация OCR: https://github.com/naptha/tesseract.js
locked: В заданной области подтверждены все три типа: время, дата и подсказка для ввода пароля.unlocked: Нет подсказки для ввода пароля, в верхней части экрана подтверждены 3 или более известных слов из строки меню macOS.unknown: Состояние, когда вышеуказанные доказательства не собраны. Пароль и Enter не отправляются.
Это консервативное определение, основанное на расположении текста на экране, а не на получении состояния macOS через OS API. Возможно состояние unknown из-за языка отображения, разрешения, обоев или изменений в UI macOS. Во избежание ошибочного ввода приоритет отдается отсутствию попыток разблокировки при недостатке доказательств.
unlock_pc() и ensure_unlocked() не принимают аргументов MCP. Учетные данные считываются только из JETKVM_PC_PASSWORD и не включаются в журналы, исключения, ответы MCP или имена файлов. Ввод учетных данных осуществляется через специальный внутренний HID-канал, не выводящий диагностические журналы. На один вызов инструмента приходится максимум один ввод пароля и Enter, автоматические повторные попытки не выполняются. Изображения для определения сохраняются как 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 в сеансе
Добавление fixture для определения блокировки с большим разнообразием языков отображения, разрешений и обоев macOS
Структурированные события аудита для каждого инструмента ввода (без включения секретной информации)
Read-only health Tool для проверки состояния WebRTC/DataChannel без ввода
Оболочка запуска для Hermes Agent, не записывающая секреты в открытом виде в файлы конфигурации
Явные нецели:
Использование Developer Mode, собственной прошивки, Cloud/Remote Access
Предоставление API изменения настроек JetKVM, Terminal, Serial, виртуальных носителей, Wake on LAN
Прямая вставка строк в японскую IME, автоматические повторные попытки при сбое аутентификации
Журнал проверки на реальном оборудовании
2026-08-18 ШАГ 1: В одном сеансе WebRTC выполнено 3 вызова
take_screenshotи 2 вызоваmove_mouse.(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подтверждено перемещение курсора ПК1 в две разные точки.Реальных вызовов click, double_click, scroll, press_key, hotkey, type_text: 0.
2026-08-18 ШАГ 2: В одном сеансе WebRTC выполнено 2 вызова
take_screenshot, 1 вызовmove_mouseи 1 вызов leftclick.(960,540)→ HID(16392,16399). Для move/click подтверждены официальный E2E HID hook, HID ready, RPC DataChannel open, WebRTC connected.Поскольку был выполнен щелчок по безопасному фону экрана блокировки, изменений в UI ПК1, кроме перемещения курсора, не было.
Реальных вызовов double_click, right click, scroll, press_key, hotkey, type_text на ШАГЕ 2: 0.
2026-08-18 ШАГ 3: В одном сеансе WebRTC выполнено 2 вызова
take_screenshotи 1 вызовpress_key("Tab")(по одному нажатию/отпусканию).Tab отправлен через официальный E2E HID hook
sendKeypress(USB HID usage0x2b). Подтверждены HID ready, RPC DataChannel open, WebRTC connected.На изображениях before/after не удалось определить четкое изменение фокуса на экране блокировки. Реальных вызовов клавиш, отличных от Tab, click, double_click, scroll, hotkey, type_text на ШАГЕ 3: 0.
2026-08-18 ШАГ 4: В одном сеансе WebRTC выполнено 3 вызова
take_screenshot, 1 вызовtype_text("abc")и 3 вызоваpress_key("Backspace").abcи Backspace отправлены через официальный E2E HID hooksendKeypress. Для всех вводов подтверждены HID ready, RPC DataChannel open, WebRTC connected. Для ввода строчных букв Shift не использовался (0 раз), Enter не использовался (0 раз).После ввода в поле пароля отобразились маркеры на 3 символа, которые исчезли после 3 нажатий Backspace. Перехода с экрана блокировки и дополнительных операций не было.
2026-08-18 ШАГ 5: В одном сеансе WebRTC выполнено 2 вызова
take_screenshot, 1 вызовmove_mouse(1400,700)и 1 вызов leftdouble_click(1400,700).Двойной щелчок отправлен через официальный E2E HID hook
sendAbsMouseMoveс двумя парами нажатий/отпусканий левой кнопки. Подтверждены HID ready, RPC DataChannel open, WebRTC connected.Выполнено в пустом месте экрана блокировки, состояние экрана не изменилось. Одиночных щелчков и других дополнительных вводов: 0.
2026-08-18 ШАГ 6: В одном сеансе WebRTC выполнено 2 вызова
take_screenshot, 1 вызовmove_mouse(1150,540)в область текста сообщения Slack и 1 вызовscroll(0,500).Прокрутка отправлена через официальный wheel-слушатель видео по пути wheel RPC JetKVM, нормализованное значение колеса:
(0,-5). Подтверждены HID ready, RPC DataChannel open, WebRTC connected.На before/after подтверждено перемещение текста сообщения Slack вверх. Щелчков, двойных щелчков, инструментов клавиатуры и других дополнительных вводов: 0.
2026-08-18 ШАГ 7 (первая попытка):
hotkey(["SHIFT","TAB"])остановлен перед отправкой HID из-за ошибки нормализации заглавногоTAB. Выполнено 2 скриншота, 0 HID-вводов на ПК1, изменений экрана нет.Добавлено исправление для нормализации псевдонима
TABвTabи unit-тест. В соответствии с условиями безопасности повторная попытка на реальном оборудовании в этот раз не выполнялась.2026-08-18 ШАГ 7 (повторная попытка): В одном сеансе WebRTC выполнено 2 вызова
take_screenshotи 1 вызовhotkey(["SHIFT","TAB"]).Отправка через официальный E2E HID hook
sendKeypressв порядке: ShiftLeft down (0xe1), Tab down (0x2b), Tab up, ShiftLeft up. Подтверждены HID ready, RPC DataChannel open, WebRTC connected.ПК1 изменился с отображения только обоев на отображение экрана блокировки. Других инструментов ввода и дополнительных реальных вводов: 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