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: site-motion-capture

基于调查的方法

截至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、#root、text=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.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在会话内复用,缩短状态判定延迟

  • 增加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.png和mouse-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。

Related MCP Connectors

Related MCP Servers

  • A
    license
    C
    quality
    D
    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
    9 npm
    14
    Apache 2.0
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables recording live website behavior on a rented GPU VM via Playwright, capturing page load, scroll, and optional hover/click actions into WebM video with jank reports, then copying the artifacts locally.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to control remote desktops through screen capture, mouse movement, and keyboard input.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to see and control an existing Linux X11 desktop over SSH by taking screenshots and performing mouse, scroll, typing, and keyboard-shortcut actions across browsers, terminals, file managers, and other apps.
    MIT