Skip to main content
Glama

JetKVM MCP Server

Ein stdio-Server, der die offizielle lokale WebUI von JetKVM mit Playwright öffnet und Bildschirmaufnahmen des angeschlossenen Computers sowie HID-Eingaben als MCP-Tools bereitstellt.

In diesem Dokument wird der Computer, der mit JetKVM verbunden ist und gesteuert wird, als „PC1“ bezeichnet, und der Computer, auf dem der MCP-Server und Playwright ausgeführt werden, als „PC2“. HID bezieht sich auf Maus- und Tastatureingaben, die JetKVM an PC1 sendet.

Implementierte Funktionen

  • PNG-Erfassung mit denselben Pixelabmessungen wie die von PC1 empfangenen Videobilder

  • Absolute Mausbewegung, Klick, Doppelklick, Scrollen

  • Einzeltaste, Hotkeys für macOS, druckbare ASCII-Eingabe

  • macOS-Sperrbildschirmerkennung, die mehrere Bildschirmmerkmale erfordert, und maximal ein Entsperrversuch

  • Wiederverwendung von BrowserContext, WebRTC und HID-Datenkanal im laufenden Betrieb

  • Einmaliger erneuter Verbindungsversuch bei WebRTC-Trennung und Diagnosespeicherung als HTML/PNG

  • Ausgabepfadbeschränkung, Ablehnung von Dateinamen, die auf Verzeichnisse außerhalb des Pfads verweisen, und Unterdrückung von Anmeldeinformationen in Protokollen

Related MCP server: Playwright MCP

Auf Untersuchungen basierender Ansatz

Das offizielle JetKVM-Repository jetkvm/kvm (Stand dev, Commit b3c29a44d9e2862b8ff7530830781803ce27b060) wurde zum Stand 2026-08-18 überprüft.

  • Die lokale Authentifizierungs-UI verwendet POST /auth/login-local und setzt bei Erfolg ein HttpOnly authToken-Cookie.

  • Das lokale WebRTC-Signaling verwendet das authentifizierungsgeschützte GET /webrtc/signaling/client.

  • Die UI fügt dem RTCPeerConnection einen recvonly-Video-Transceiver hinzu und setzt den empfangenen MediaStream als srcObject eines <video>-Elements.

  • Diese Implementierung führt diese offizielle UI unverändert mit Playwright aus und zeichnet das decodierte Videobild auf eine Canvas, um es als PNG zu speichern.

Eigenes Signaling, Developer Mode, eigene Firmware, Cloud/Remote Access und JetKVM-Konfigurationsänderungen werden nicht verwendet. Virtuelle Medien, Wake-on-LAN, Terminal, Serielle Schnittstelle usw. werden ebenfalls nicht bereitgestellt.

Architektur

Beim Start des MCP-Servers werden jeweils eine Playwright-Chromium-Instanz, ein BrowserContext und eine Seite erstellt, einmalig bei JetKVM angemeldet und gewartet, bis das WebRTC-Video bereit ist. Alle Tools teilen sich dieselbe Seite und dieselbe WebRTC-/DataChannel-Sitzung; gleichzeitige Aufrufe werden nacheinander verarbeitet. Bei normalen Tool-Aufrufen wird der Browser weder neu gestartet noch eine erneute Anmeldung durchgeführt.

Für Eingaben werden page.mouse / page.keyboard von Playwright nicht verwendet. Diese würden nur Chromium auf PC2 steuern und können nicht garantieren, dass die Eingaben bei PC1 ankommen.

Maus und Tastatur werden bevorzugt über window.__kvmTestHooks aufgerufen, die die offizielle JetKVM-WebUI für E2E-Tests bereitstellt. Falls der Hook nicht verfügbar ist, werden DOM-Ereignisse an die Ereignis-Listener gesendet, die die offizielle UI auf <video> und document registriert hat. Das Scrollen erfolgt immer über den offiziellen Wheel-Listener der UI für das Video. Dieses Design vermeidet die Implementierung eigener HID-Pakete und nutzt den HID-RPC-Handshake, die DataChannel-Auswahl und den Fallback für ältere Versionen innerhalb der offiziellen UI.

__kvmTestHooks ist keine stabile externe API von JetKVM. Da diese Implementierung auf dem genannten Commit basiert, muss die Kompatibilität der Eingabesysteme nach JetKVM-Updates erneut überprüft werden.

Hauptkomponenten:

Datei

Verantwortung

Designbegründung

server.ts

MCP-Schema und stdio-Lebenszyklus

Playwright und Anmeldeinformationen nicht der MCP-Grenze aussetzen

session.ts

Browser/WebRTC-Persistenz, Serialisierung, Wiederverbindung

Konflikte vermeiden, denselben DataChannel für alle Tools verwenden

capture.ts

Bilderfassung mit Original-Pixelabmessungen des empfangenen Videos, Fehlerdiagnose

Nur das PC1-Video verarbeiten, nicht die gesamte JetKVM-UI

input.ts

Dispatch an offizielle HID-Hooks und Wheel-RPC

Eingaben zuverlässig an PC1 senden, nicht an den PC2-Browser

keyboard.ts

Zuordnung von MCP-Tastennamen, KeyboardEvent.code und USB-HID

Schlüsselumwandlung und -sendung trennen

unlock.ts

OCR-Dreifachbewertung und maximal eine Authentifizierung

Falscheingaben in normale Anwendungen bei Fehlentscheidungen verhindern

Tool-Aufruffluss:

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

Bei einer WebRTC-Trennung wird dieselbe Seite einmal neu geladen, um die Verbindung wiederherzustellen. Wenn die Verbindung nicht innerhalb von 30 Sekunden wiederhergestellt ist, werden Diagnosedateien gespeichert und ein Fehler zurückgegeben, der die Möglichkeit einer anderen JetKVM-WebRTC-Sitzung einschließt.

JetKVM kann bei gleichzeitigen WebRTC-Sitzungen zu Konflikten führen. Öffnen Sie während der Nutzung des MCP-Servers nicht dieselbe JetKVM-KVM-Ansicht in einem normalen Chrome/Safari usw.

Offizielle Quellen:

Einrichtung

Node.js 20 oder höher ist erforderlich.

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

Bei Verwendung einer .env-Datei lädt der Server selbst dotenv nicht automatisch; die Datei muss daher in der Start-Shell geladen werden.

cp .env.example .env
# .envへ実値を設定(Gitにはcommitしない)
set -a
source .env
set +a
npm run build
npm start

Nur beim ersten Mal wird Chromium installiert. Bei normalen Starts ohne Aktualisierung der Abhängigkeiten ist eine erneute Ausführung nicht erforderlich.

npx playwright install chromium

JETKVM_PC_PASSWORD ist ausschließlich für die Entsperrung von PC1 (macOS) vorgesehen. Übergeben Sie es nicht als Tool-Argument und verwalten Sie es nur in der lokalen .env-Datei auf PC2. Die .env-Datei ist in der gitignore enthalten, aber duplizieren Sie sie nicht versehentlich unter einem anderen Namen. Es wird empfohlen, sie nicht im Klartext in Konfigurationsdateien wie Hermes zu speichern, sondern die Umgebungsvariable von der Start-Shell zu erben.

Direkte Überprüfung der PNG-Erfassung

npm run screenshot -- current-screen.png

Bei Erfolg wird die Datei screenshots/current-screen.png gespeichert. Der Dateiname darf nicht außerhalb von JETKVM_SCREENSHOT_DIR liegen und nur .png ist erlaubt.

Bei jeder Ausführung wird nach einer 5-sekündigen Wartezeit für die SPA-Initialisierung vor dem Warten auf das Video auch die folgende Diagnoseinformation gespeichert und auf stderr ausgegeben. Wenn kein Video erfasst werden kann, bleiben die Diagnosedateien erhalten.

  • Aktuelle URL, Seitentitel, erste 2000 Zeichen des Texts

  • Anzahl der Elemente video, password input, form, #root, text=JetKVM

  • screenshots/debug-page.html

  • screenshots/debug-page.png (ganze Seite)

MCP-Konfigurationsbeispiel

{
  "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"
      }
    }
  }
}

Veröffentlichte Tools und MCP-Argumente:

Tool

Argumente

Aktion

take_screenshot

filename?: string

PNG mit denselben Pixelabmessungen wie das empfangene Video speichern und zurückgeben

move_mouse

x: int, y: int

Absolute Bewegung zu PC1-Videokoordinaten

click

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

Einmaliger Klick an der angegebenen Position

double_click

x: int, y: int

Zwei Sätze von linkem Button down/up senden

scroll

dx: number, dy: number

Scroll-RPC über den offiziellen Wheel-Listener der UI senden

press_key

key: string

Entsprechende Taste down/up

hotkey

keys: string[]

Tasten nacheinander down, in umgekehrter Reihenfolge up. META/CMD-Unterstützung

type_text

text: string

Druckbare ASCII-Zeichen als US-Tastaturlayout eingeben

unlock_pc

Keine

Nur bei eindeutigem Sperrbildschirm maximal einen Authentifizierungsversuch durchführen

ensure_unlocked

Keine

Wenn bereits entsperrt, keine Eingabe; nur bei gesperrtem Bildschirm gemeinsame Entsperrung durchführen

Das Schreibziel für Screenshots ist auf das Verzeichnis screenshots/ direkt im aktuellen Arbeitsverzeichnis des Serverprozesses beschränkt. Wenn JETKVM_SCREENSHOT_DIR angegeben ist, muss der normalisierte Pfad mit diesem Ort übereinstimmen. Dateinamen, die auf Verzeichnisse außerhalb dieses Pfads verweisen (z. B. ../ oder absolute Pfade), werden abgelehnt.

Sicherheitsspezifikation für die PC1-Entsperrung

Der Sperrzustand wird durch bereichsbezogene OCR des PC1-Videos mit Tesseract.js (WASM, inklusive englischer und japanischer Sprachdaten) auf PC2 bestimmt und als einer von drei Werten (locked / unlocked / unknown) klassifiziert. Bilder oder OCR-Ergebnisse werden nicht an externe Dienste gesendet.

OCR-Implementierung: https://github.com/naptha/tesseract.js

  • locked: In einem bestimmten Bereich werden alle drei Elemente (Uhrzeit, Datum, Passworthinweis) bestätigt.

  • unlocked: Kein Passworthinweis vorhanden, und im oberen Bildschirmbereich werden drei oder mehr bekannte macOS-Menüleistenbegriffe bestätigt.

  • unknown: Die oben genannten Nachweise liegen nicht vollständig vor. Es werden weder Passwort noch Enter gesendet.

Dies ist keine Methode, die den macOS-Status über eine OS-API abruft, sondern eine konservative Bewertung basierend auf der Textanordnung auf dem Bildschirm. Aufgrund der Anzeigesprache, Auflösung, des Hintergrundbilds oder von macOS-UI-Änderungen kann der Zustand unknown sein. Um Falscheingaben zu vermeiden, wird bei unzureichenden Nachweisen kein Entsperrversuch unternommen.

unlock_pc() und ensure_unlocked() akzeptieren keine MCP-Argumente. Die Anmeldeinformationen werden nur aus JETKVM_PC_PASSWORD gelesen und nicht in Protokollen, Ausnahmen, MCP-Antworten oder Dateinamen aufgenommen. Die Eingabe der Anmeldeinformationen erfolgt über einen speziellen internen HID-Pfad, der keine Diagnoseprotokolle ausgibt. Pro Tool-Aufruf erfolgt maximal eine Passworteingabe und ein Enter; es gibt keine automatischen Wiederholungsversuche. Die Bewertungsbilder werden als unlock-before.png, ensure-unlocked-before.png und das Ergebnis als unlock-after.png nur innerhalb von screenshots/ gespeichert.

Der zurückgegebene status ist einer der folgenden: unlocked, already_unlocked, not_lock_screen, state_unknown, unlock_failed.

Tests

npm test
npm run build

Roadmap

Zukünftige Kandidaten:

  • Verkürzung der Latenz bei der Zustandsbewertung durch Wiederverwendung des OCR-Workers innerhalb der Sitzung

  • Erweiterung der Lock-Erkennungs-Fixtures um Variationen der macOS-Anzeigesprache, -auflösung und -hintergrundbilder

  • Strukturierte Audit-Ereignisse (ohne vertrauliche Informationen) für jedes Eingabe-Tool

  • Read-only Health-Tool zur Überprüfung des WebRTC-/DataChannel-Status ohne Eingabe

  • Start-Wrapper für Hermes Agent, der vertrauliche Informationen nicht direkt in Konfigurationsdateien speichert

Explizite Nicht-Ziele:

  • Nutzung von Developer Mode, eigener Firmware, Cloud/Remote Access

  • Bereitstellung von JetKVM-Konfigurationsänderungs-API, Terminal, Serieller Schnittstelle, Virtuellen Medien, Wake-on-LAN

  • Direkte Zeichenketteneingabe in japanische IMEs, automatische Wiederholungsversuche bei Authentifizierungsfehlern

Protokoll der Hardware-Überprüfung

  • 2026-08-18 SCHRITT 1: take_screenshot 3 Mal, move_mouse 2 Mal in derselben WebRTC-Sitzung ausgeführt.

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

  • Beide Male wurden der offizielle E2E-HID-Hook, HID ready, RPC DataChannel open und WebRTC connected bestätigt.

  • In mouse-a.png und mouse-b.png wurde bestätigt, dass sich der PC1-Cursor zu zwei verschiedenen Punkten bewegt hat.

  • Hardware-Aufrufe von click, double_click, scroll, press_key, hotkey, type_text: 0 Mal.

  • 2026-08-18 SCHRITT 2: take_screenshot 2 Mal, move_mouse 1 Mal, left click 1 Mal in derselben WebRTC-Sitzung ausgeführt.

  • (960,540) → HID (16392,16399). Sowohl für move als auch click wurden der offizielle E2E-HID-Hook, HID ready, RPC DataChannel open und WebRTC connected bestätigt.

  • Da auf einen sicheren Hintergrund des Sperrbildschirms geklickt wurde, gab es außer der Cursorbewegung keine Änderungen der PC1-Benutzeroberfläche.

  • Hardware-Aufrufe von double_click, right click, scroll, press_key, hotkey, type_text in SCHRITT 2: 0 Mal.

  • 2026-08-18 SCHRITT 3: take_screenshot 2 Mal, press_key("Tab") 1 Mal (jeweils 1 Mal down/up) in derselben WebRTC-Sitzung ausgeführt.

  • Tab wurde über den offiziellen sendKeypress E2E-HID-Hook (USB-HID Usage 0x2b) gesendet. HID ready, RPC DataChannel open und WebRTC connected wurden bestätigt.

  • In den Before/After-Bildern konnte keine eindeutige Fokusänderung auf dem Sperrbildschirm festgestellt werden. Hardware-Aufrufe von anderen Tasten als Tab, click, double_click, scroll, hotkey, type_text in SCHRITT 3: 0 Mal.

  • 2026-08-18 SCHRITT 4: take_screenshot 3 Mal, type_text("abc") 1 Mal, press_key("Backspace") 3 Mal in derselben WebRTC-Sitzung ausgeführt.

  • abc und Backspace wurden über den offiziellen sendKeypress E2E-HID-Hook gesendet. HID ready, RPC DataChannel open und WebRTC connected wurden bei allen Eingaben bestätigt. Da Kleinbuchstaben eingegeben wurden, gab es 0 Mal Shift und 0 Mal Enter.

  • Nach der Eingabe wurden im Passwortfeld Markierungen für drei Zeichen angezeigt, die nach 3 Mal Backspace alle verschwanden. Es gab keinen Übergang vom Sperrbildschirm und keine weiteren Aktionen.

  • 2026-08-18 SCHRITT 5: take_screenshot 2 Mal, move_mouse(1400,700) 1 Mal, left double_click(1400,700) 1 Mal in derselben WebRTC-Sitzung ausgeführt.

  • Der Doppelklick wurde über den offiziellen sendAbsMouseMove E2E-HID-Hook gesendet, wobei der linke Button jeweils 2 Mal down/up gesendet wurde. HID ready, RPC DataChannel open und WebRTC connected wurden bestätigt.

  • Die Aktion wurde an einer leeren Stelle auf dem Sperrbildschirm durchgeführt, ohne den Bildschirmzustand zu ändern. Es gab 0 einzelne Klicks und keine weiteren Eingaben.

  • 2026-08-18 SCHRITT 6: take_screenshot 2 Mal, move_mouse(1150,540) 1 Mal in den Textbereich einer Slack-Nachricht, scroll(0,500) 1 Mal in derselben WebRTC-Sitzung ausgeführt.

  • Das Scrollen wurde über den offiziellen Video-Wheel-Listener an den JetKVM-Wheel-RPC-Pfad gesendet, der normalisierte Wheel-Wert war (0,-5). HID ready, RPC DataChannel open und WebRTC connected wurden bestätigt.

  • In den Before/After-Bildern wurde bestätigt, dass sich der Slack-Nachrichtentext nach oben bewegt hat. Es gab 0 Klicks, Doppelklicks, Tastatur-Tools und keine weiteren Eingaben.

  • 2026-08-18 SCHRITT 7 erster Versuch: hotkey(["SHIFT","TAB"]) wurde aufgrund eines Normalisierungsfehlers für den Großbuchstaben TAB vor dem HID-Dispatch gestoppt. 2 Screenshots, 0 HID-Eingaben an PC1, keine Bildschirmänderung.

  • Eine Korrektur zur Normalisierung des TAB-Alias auf Tab und ein Unit-Test wurden hinzugefügt. Gemäß den Sicherheitsbedingungen wurde in diesem Durchgang kein erneuter Hardware-Test durchgeführt.

  • 2026-08-18 SCHRITT 7 erneuter Versuch: take_screenshot 2 Mal, hotkey(["SHIFT","TAB"]) 1 Mal in derselben WebRTC-Sitzung ausgeführt.

  • Über den offiziellen sendKeypress E2E-HID-Hook wurden nacheinander ShiftLeft down (0xe1), Tab down (0x2b), Tab up, ShiftLeft up gesendet. HID ready, RPC DataChannel open und WebRTC connected wurden bestätigt.

  • PC1 wechselte von der Anzeige nur des Hintergrundbilds zur Anzeige des Sperrbildschirms. Es gab 0 andere Eingabe-Tools und keine weiteren Hardware-Eingaben.

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