Skip to main content
Glama

JetKVM MCP Server

JetKVM의 공식 로컬 웹 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, #root, text=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

없음

이미 해제된 경우 입력 없음, 잠긴 경우만 공통 해제 처리

스크린샷의 쓰기 대상은 서버 프로세스의 현재 디렉토리 바로 아래에 있는 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.pngscreenshots/ 내에만 저장합니다.

반환값의 statusunlocked, 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_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 커서가 다른 두 지점으로 이동한 것을 확인.

  • 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