Skip to main content
Glama

JetKVM MCP Server

这是JetKVM的官方本地Web UI通过Playwright打开的stdio服务器,提供连接目标计算机的屏幕捕获和HID输入作为MCP工具。

本文档中,连接到JetKVM并接受操作的计算机称为“PC1”,运行MCP Server和Playwright的计算机称为“PC2”。HID是指JetKVM发送给PC1的鼠标和键盘输入。

已实现功能

  • 获取与PC1接收到的视频帧相同像素尺寸的PNG

  • 绝对鼠标移动、单击、双击、滚动

  • 单键、macOS快捷键、可打印ASCII输入

  • 需要多种屏幕特征的macOS锁屏判定,以及最多一次的限制解锁尝试

  • BrowserContext、WebRTC和HID DataChannel的常驻复用

  • WebRTC断开时的一次性重连,以及HTML/PNG诊断保存

  • 输出目录限制、拒绝指向目录外的文件名、凭证日志抑制

Related MCP server: Playwright MCP

基于调查的方法

截至2026-08-18,已确认JetKVM官方jetkvm/kvm仓库(dev分支,提交b3c29a44d9e2862b8ff7530830781803ce27b060)。

  • 本地认证UI使用POST /auth/login-local,成功时设置HttpOnly的authToken Cookie。

  • 本地WebRTC信令使用受认证保护的GET /webrtc/signaling/client

  • UI向RTCPeerConnection添加recvonly视频收发器,并将接收到的MediaStream设置为<video>srcObject

  • 本实现直接通过Playwright运行此官方UI,将解码后的视频帧绘制到canvas并生成PNG。

不使用自定义信令、开发者模式、自定义固件、云/远程访问、JetKVM设置更改。也不公开虚拟媒体、Wake on LAN、终端、串口等。

架构

MCP Server启动时,仅创建一个Playwright Chromium、BrowserContext和page,登录JetKVM一次并等待WebRTC视频就绪。所有工具共享同一个page和WebRTC/DataChannel会话,同步调用按顺序处理。通常的工具调用不会导致浏览器重启或重新登录。

输入不使用Playwright的page.mouse/page.keyboard。因为它们只操作PC2上的Chromium,无法保证到达PC1。

鼠标和键盘优先调用JetKVM官方Web UI为E2E测试公开的window.__kvmTestHooks。如果hook不可用,则向官方UI注册的<video>document事件监听器发送DOM事件。滚动始终通过官方UI的video wheel监听器。此设计无需实现自定义HID数据包,而是复用官方UI内部的HID RPC握手、DataChannel选择以及旧版本的回退。

__kvmTestHooks不是JetKVM稳定的外部API。本实现已确认上述提交中的实现,因此在JetKVM更新后请重新验证输入系统的兼容性。

主要组件:

文件

职责

设计理由

server.ts

MCP schema和stdio生命周期

不将Playwright或凭证暴露给MCP边界

session.ts

Browser/WebRTC常驻、序列化、重连

避免竞争,所有工具使用同一DataChannel

capture.ts

以原始像素尺寸获取接收视频帧、故障诊断

仅处理PC1视频,而非整个JetKVM UI

input.ts

分发到官方HID hook/wheel RPC

确保到达PC1,而非操作PC2浏览器

keyboard.ts

MCP键名、KeyboardEvent.code、USB HID的对应关系

分离键转换和发送处理

unlock.ts

OCR三值判定和最多一次认证

防止误判时向正常应用输入秘密

工具调用的流程:

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

WebRTC断开时,仅重新加载同一page一次以重连。如果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,因此需要在启动shell中加载它。

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。不要将其传递给工具参数,仅通过PC2本地的.env管理。.env已添加到gitignore,但请勿错误地以其他名称复制。不建议在Hermes等配置文件中以明文形式写入,建议通过启动shell继承环境变量。

PNG获取直接验证

npm run screenshot -- current-screen.png

成功时,保存screenshots/current-screen.png。文件名不能超出JETKVM_SCREENSHOT_DIR之外,且仅允许.png扩展名。

每次执行时,由于SPA初始化需等待5秒,然后在等待视频之前也保存以下诊断信息并显示在stderr上。即使无法获取视频,诊断文件也会保留。

  • 当前URL、页面标题、正文前2000个字符

  • video、密码输入框、form#roottext=JetKVM 的元素数量

  • screenshots/debug-page.html

  • screenshots/debug-page.png(全页)

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参数:

工具

参数

行为

take_screenshot

filename?: string

保存并返回与接收视频相同像素尺寸的PNG

move_mouse

x: int, y: int

绝对移动到PC1视频坐标

click

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

在指定位置单击一次

double_click

x: int, y: int

发送两组左键按下/释放

scroll

dx: number, dy: number

通过官方UI的wheel监听器发送滚动RPC

press_key

key: string

对应键按下/释放

hotkey

keys: string[]

按顺序按下,逆序释放。支持META/CMD

type_text

text: string

以US键盘布局输入可打印ASCII字符

unlock_pc

仅在明确锁屏时尝试最多一次认证

ensure_unlocked

如果已解锁则不输入,仅对锁定状态执行通用解锁处理

屏幕截图仅写入服务器进程当前目录下的screenshots/目录。如果指定了JETKVM_SCREENSHOT_DIR,规范化后也必须与此位置一致。拒绝包含../或绝对路径等指向此目录外的文件名。

PC1解锁安全规范

锁定状态通过PC2上的Tesseract.js(WASM,包含英语和日语数据)对PC1视频进行区域OCR,判定为locked/unlocked/unknown三值。不将图像或OCR结果发送到外部服务。

OCR实现:https://github.com/naptha/tesseract.js

  • locked:在指定区域内同时检测到时间、日期、密码提示三种类型

  • unlocked:无密码提示,且在画面上方检测到三种以上已知的macOS菜单栏词语

  • unknown:未满足上述证据的状态。不发送密码也不发送回车

这不是通过OS API获取macOS状态的方法,而是基于屏幕上文字布局的保守判定。可能因显示语言、分辨率、壁纸、macOS UI变化而变为unknown。为避免误输入,优先在证据不足时不做解锁尝试。

unlock_pc()ensure_unlocked()不接受MCP参数。凭证仅从JETKVM_PC_PASSWORD读取,不会包含在日志、异常、MCP响应或文件名中。凭证输入使用不产生诊断日志的专用内部HID路径。每次工具调用最多输入一次密码和回车,不会自动重试。判定图像保存为unlock-before.pngensure-unlocked-before.png,结果确认保存为unlock-after.png,仅在screenshots/目录内。

返回值的statusunlockedalready_unlockednot_lock_screenstate_unknownunlock_failed之一。

测试

npm test
npm run build

路线图

未来候选:

  • 通过OCR worker在会话内复用,缩短状态判定延迟

  • 增加macOS显示语言、分辨率、壁纸变体的锁定判定fixture

  • 每个输入工具的结构化审计事件(不包含秘密信息)

  • 无需输入即可检查WebRTC/DataChannel状态的只读健康工具

  • 针对Hermes Agent的启动包装器,避免将秘密信息直接写入配置文件

明确非目标:

  • 使用开发者模式、自定义固件、云/远程访问

  • 公开JetKVM设置更改API、终端、串口、虚拟媒体、Wake on LAN

  • 直接注入日语IME字符串、认证失败时自动重试

实机验证日志

  • 2026-08-18 步骤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 步骤2:在同一WebRTC会话中执行take_screenshot 2次,move_mouse 1次,左键click 1次。

  • (960,540) → HID (16392,16399)。move/click均确认了官方E2E HID hook、HID ready、RPC DataChannel open、WebRTC connected。

  • 由于点击了安全的锁屏背景,除光标移动外无其他PC1 UI变化。

  • double_click、右键click、scroll、press_key、hotkey、type_text在步骤2中的实机调用次数为0。

  • 2026-08-18 步骤3:在同一WebRTC会话中执行take_screenshot 2次,press_key("Tab") 1次(按下/释放各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在步骤3中的实机调用次数为0。

  • 2026-08-18 步骤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 步骤5:在同一WebRTC会话中执行take_screenshot 2次,move_mouse(1400,700) 1次,左键double_click(1400,700) 1次。

  • 双击通过官方sendAbsMouseMove E2E HID hook发送左键按下/释放各2次。确认了HID ready、RPC DataChannel open、WebRTC connected。

  • 在锁屏的空白区域执行,无屏幕状态变化。未进行单次点击及其他额外输入。

  • 2026-08-18 步骤6:在同一WebRTC会话中执行take_screenshot 2次,对Slack消息正文区域执行move_mouse(1150,540) 1次,scroll(0,500) 1次。

  • 滚动通过官方video wheel监听器发送到JetKVM的wheel RPC路径,归一化wheel值为(0,-5)。确认了HID ready、RPC DataChannel open、WebRTC connected。

  • 通过before/after确认Slack消息正文向上滚动。click、double_click、键盘类工具及其他额外输入次数为0。

  • 2026-08-18 步骤7首次:hotkey(["SHIFT","TAB"])因大写TAB的归一化错误在HID分发前停止。截图2次,PC1 HID输入0次,无画面变化。

  • 已添加将TAB别名归一化为Tab的修正和单元测试。根据安全条件,本次未进行实机重试。

  • 2026-08-18 步骤7重试:在同一WebRTC会话中执行take_screenshot 2次,hotkey(["SHIFT","TAB"]) 1次。

  • 通过官方sendKeypress E2E HID hook按顺序发送ShiftLeft按下 (0xe1)、Tab按下 (0x2b)、Tab释放、ShiftLeft释放。确认了HID ready、RPC DataChannel open、WebRTC connected。

  • PC1从仅显示壁纸变为显示锁屏界面。其他输入工具和额外实机输入次数为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