English README: README.en.md
让 Midscene 直接控制你的桌面应用与窗口。本库提供一个 PC 设备接口及服务实现,统一鼠标、键盘、剪贴板与截图等能力,并与 @midscene/core 无缝协作,让你用自然语言驱动桌面自动化。
PCDevice)。localPCService)与远程服务(createRemotePCService)两种模式。远程模式可以在服务器上部署一个带桌面的 docker 镜像(DockerHub 地址,Git地址),然后客户端程序就不需要在桌面环境下运行了,比如可以放到服务器上去定时运行等。@midscene/core 的定位与动作体系深度集成。注意: 由于依赖的库文件需要本地化编译,耗时可能略久。
pnpm add midscene-pc
使用 npx 直接启动服务:
npx midscene-pc@latest
指定端口与主机:
npx midscene-pc --port 4000 --host 127.0.0.1 --token your-remote-service-token
查看帮助:
npx midscene-pc --help
项目支持通过环境变量进行配置,你可以创建 .env 文件或设置系统环境变量:
MIDSCENE_USE_QWEN3_VL: 是否使用 Qwen3 VL 模型,默认 trueOPENAI_BASE_URL: OpenAI API 基础 URL,默认 https://dashscope.aliyuncs.com/compatible-mode/v1OPENAI_API_KEY: OpenAI API 密钥MIDSCENE_MODEL_NAME: 使用的模型名称,默认 qwen3-vl-plusPORT: 服务端口,默认 3333HOST: 服务主机,默认 0.0.0.0TOKEN: 服务访问令牌,env中默认 your-remote-service-token(如果设置了令牌,客户端调用时需要使用?token=your-remote-service-token`)LOG_LEVEL: 日志级别,默认 info(可选:error, warn, info, http, verbose, debug, silly)LOG_DIR: 日志目录,默认 ./logsLOG_MAX_SIZE: 日志文件最大大小,默认 20m(支持 K、M、G 单位)LOG_MAX_FILES: 日志文件保留时间,默认 14d(支持 d、m 等单位)LOG_DATE_PATTERN: 日志文件日期格式,默认 YYYY-MM-DDNODE_ENV: 设置为 development 时会在控制台输出彩色日志,生产环境建议设置为 production.env 文件PORT=3333
HOST=0.0.0.0
# 环境配置
NODE_ENV=production
# 日志配置
LOG_LEVEL=info
LOG_DIR=./logs
LOG_MAX_SIZE=20m
LOG_MAX_FILES=14d
LOG_DATE_PATTERN=YYYY-MM-DD
libxss1、imagemagick,均使用 apt install 直接安装node_modules 是没用的import "dotenv/config";
import { PCDevice, PCAgent, localPCService } from "midscene-pc";
async function main() {
const device = new PCDevice({
pcService: localPCService,
launchOptions: {
// windowInfo: { appName: 'Edge' },
screenArea: {
preferManual: true, // 启动手动绘制模式。如果不传参数,默认primary显示器,也可以传递显示器的id、截图区域等,具体可以参考代码实现
},
},
});
await device.launch(); // 必须先初始化设备
const agent = new PCAgent(device);
await agent.aiAction("打开谷歌,搜索 midscene");
const answer = await agent.aiOutput("描述一下当前桌面截图"); // PCAgent增加了一个支持直接返回答案的方法。
console.log(answer);
}
main().catch(console.error);
PCAgent 支持对定位结果做本地缓存,适用于 UI 稳定、重复运行的脚本场景,可减少重复定位带来的耗时与模型调用。
启用缓存:创建 PCAgent 时指定缓存 id(同一 id 会复用同一份缓存数据):
const agent = new PCAgent(device, {
cache: { id: "my-cache" },
});
使用缓存:在需要缓存的 aiLocate / aiTap 调用中,提供稳定的 xpath 并开启 cacheable:
await agent.aiTap("任务栏上的 Windows 菜单", {
xpath: "/taskbar/menu",
cacheable: true,
});
缓存数据默认写入 ./cache/<id>。如果 UI / 分辨率 / 缩放变化导致缓存失效,可调用 agent.clearCache() 或更换缓存 id。示例见 cache.ts。
PCAgent 增加了一个支持行动后返回答案的方法 aiOutput。自带的ai方法不返回最终有效信息,这个方法可以执行完操作之后返回最终的有效对话信息。
在目标机器上启动服务,然后用 HTTP 客户端驱动:
import "dotenv/config";
import {
startServer,
createRemotePCService,
PCDevice,
PCAgent,
} from "midscene-pc";
async function main() {
// 测试时可以直接在本机启动服务(默认 http://0.0.0.0:3333)
await startServer();
// 通过 HTTP 驱动
const pcService = createRemotePCService("http://localhost:3333");
const device = new PCDevice({ pcService, launchOptions: {} });
await device.launch();
const agent = new PCAgent(device);
await agent.aiAction("描述一下当前桌面的情况");
}
main().catch(console.error);

docker run -it -d --rm --name=midscene-ubuntu-desktop \
-p 10081:10081 -p 10089:10089 -p 3333:3333 \
--tmpfs /run --tmpfs /run/lock --tmpfs /tmp \
--cap-add SYS_BOOT --cap-add SYS_ADMIN \
-v /sys/fs/cgroup:/sys/fs/cgroup:rw \
-v ./data:/mnt/data \
--cgroupns=host --privileged --shm-size=4g \
-e L=zh_CN \
-e SSH_PASS=midscene-pc \
-e VNC_PASS=midscene-pc \
-e VNC_PASS_RO=midscene_pc \
ppagent/midscene-ubuntu-desktop:latest
提示: 服务默认启动在
3333端口。
详情可以参考 midscene-pc-docker
本仓库内置多个 demo,含本地与远程两种用法。
pnpm install
pnpm dev
# 模拟远程运行
pnpm dev --remote
| Method | Path | Body | Response | 说明 |
|---|---|---|---|---|
| GET | /health |
- | { ok: true } |
健康检查 |
| GET | /monitors |
- | Monitor[] |
显示器列表 |
| GET | /monitors/:id/capture |
- | image/png |
指定显示器截图 |
| POST | /monitor/point |
{ x, y } |
Monitor \| null |
点位所在显示器 |
| GET | /windows |
- | Window[] |
窗口列表 |
| GET | /windows/:id/capture |
- | image/png |
指定窗口截图 |
| POST | /mouse/set-position |
{ x, y } |
{ success: true } |
设置鼠标位置 |
| GET | /mouse/position |
- | { x, y } |
获取鼠标位置 |
| POST | /mouse/click |
{ button } |
{ success: true } |
单击(MouseButton) |
| POST | /mouse/double-click |
{ button } |
{ success: true } |
双击(MouseButton) |
| POST | /mouse/press |
{ button } |
{ success: true } |
按下(MouseButton) |
| POST | /mouse/release |
{ button } |
{ success: true } |
抬起(MouseButton) |
| POST | /mouse/move |
{ points: Point[] } |
{ success: true } |
路径移动 |
| POST | /mouse/scroll/left |
{ distance } |
{ success: true } |
水平滚动左 |
| POST | /mouse/scroll/right |
{ distance } |
{ success: true } |
水平滚动右 |
| POST | /mouse/scroll/up |
{ distance } |
{ success: true } |
垂直滚动上 |
| POST | /mouse/scroll/down |
{ distance } |
{ success: true } |
垂直滚动下 |
| POST | /keyboard/press |
{ keys: number[] } |
{ success: true } |
按下按键(KeyCode) |
| POST | /keyboard/release |
{ keys: number[] } |
{ success: true } |
释放按键(KeyCode) |
| POST | /keyboard/type |
{ text } |
{ success: true } |
输入文本 |
| POST | /clipboard/set |
{ content } |
{ success: true } |
设置剪贴板 |
| GET | /clipboard/get |
- | { content } |
获取剪贴板 |
| POST | /screenshot |
{ saveFileFullPath? } |
{ rect, monitor } |
捕获屏幕(返回矩形与显示器信息) |
{ id, name, x, y, width, height, rotation, scaleFactor, frequency, isPrimary }{ id, appName, title, x, y, width, height, currentMonitor: Monitor }MIT
$ claude mcp add midscene-pc \
-- python -m otcore.mcp_server <graph>