功能特性
- 使用 Javascript SDK 或 YAML 格式编写自动化脚本。
- 网页或移动应用
- 用于调试的可视化报告:通过我们的测试报告和 Playground,可以轻松理解、回放和调试整个过程。
- 允许其他 MCP Client 直接使用 Midscene 的能力:Web MCP 、Android MCP
- 三种 API 类型:交互 API(与用户界面交互)、数据提取 API(从用户界面和 DOM 中提取数据)、实用 API: 实用函数(如 aiAssert() (断言), aiLocate() (定位), aiWaitFor() (等待))
使用Midscene有两种方式:chrome插件、集成到代码
一、Chrome安装使用
1. 前往 Chrome 扩展商店安装 Midscene 扩展
2. 启动扩展(可能默认折叠在 Chrome 扩展列表中),通过粘贴 Key=Value 格式配置插件环境:
OPENAI_API_KEY="sk-replace-by-your-own"
# ...可能还有其他配置项,一并贴入
开始体验
它一共有三个关键操作 Tab:
- Action: 与网页进行交互,这就是所谓的自动规划(Auto Planning)。比如(在搜索框中输入 Midscene 点击登录按钮)
- Query: 从界面中提取 JSON 数据(提取页面中的用户 ID,返回 \{ id: string \})
- Assert: 验证页面(页面标题是 Midscene)
- Tap: 在某个元素上点击,这就是所谓的即时操作(Instant Action)。
二、将 Midscene 集成到代码
官方提供了4种方式:
这里有几种不同集成形式的文档:
- 使用 Chrome 插件的桥接模式
- 与 Puppeteer 集成
- 与 Playwright 集成
一)使用 YAML 格式的自动化脚本
全局安装 @midscene/cli
npm i -g @midscene/cli
# 或在项目中安装
npm i @midscene/cli --save-dev
基于 .yaml 文件的自动化测试方法,编写一个名为 bing-search.yaml
web:
url: https://www.bing.com
tasks:
- name: 搜索天气
flow:
- ai: 搜索 "今日天气"
- sleep: 3000
- name: 检查结果
flow:
- aiAssert: 结果中展示了天气信息
或者驱动安卓设备的自动化任务(需要使用 adb 连接安卓设备)
android:
# launch: https://www.bing.com
deviceId: s4ey59
tasks:
- name: 搜索天气
flow:
- ai: 打开浏览器并导航到 bing.com
- ai: 搜索 "今日天气"
- sleep: 3000
- aiAssert: 结果显示天气信息
运行脚本
midscene ./bing-search.yaml
# 或者如果你在项目中安装了 midscene
npx midscene ./bing-search.yaml
一个标准的 .yaml 脚本文件包含 web 或 android 部分配置环境,以及一个 tasks 部分来定义自动化任务。
web:
url: https://www.bing.com
# tasks 部分定义了要执行的一系列步骤
tasks:
- name: 搜索天气
flow:
- ai: 搜索 "今日天气"
- sleep: 3000
- aiAssert: 结果显示天气信息
web 部分
web:
# 访问的 URL,必填。如果提供了 `serve` 参数,则提供相对路径
url: <url>
# 在本地路径下启动一个静态服务,可选
serve: <root-directory>
# 浏览器 UA,可选
userAgent: <ua>
# 浏览器视口宽度,可选,默认 1280
viewportWidth: <width>
# 浏览器视口高度,可选,默认 960
viewportHeight: <height>
# 浏览器设备像素比,可选,默认 1
deviceScaleFactor: <scale>
# JSON 格式的浏览器 Cookie 文件路径,可选
cookie: <path-to-cookie-file>
# 等待网络空闲的策略,可选
waitForNetworkIdle:
# 等待超时时间,可选,默认 2000ms
timeout: <ms>
# 是否在等待超时后继续,可选,默认 true
continueOnNetworkIdleError: <boolean>
# 输出 aiQuery/aiAssert 结果的 JSON 文件路径,可选
output: <path-to-output-file>
# 是否保存日志内容到 JSON 文件,可选,默认 `false`。如果为 true,保存到 `unstableLogContent.json` 文件中。如果为字符串,则保存到该字符串指定的路径中。日志内容的结构可能会在未来发生变化。
unstableLogContent: <boolean | path-to-unstable-log-file>
# 是否限制页面在当前 tab 打开,可选,默认 true
forceSameTabNavigation: <boolean>
# 桥接模式,可选,默认 false,可以为 'newTabWithUrl' 或 'currentTab'。更多详情请参阅后文
bridgeMode: false | 'newTabWithUrl' | 'currentTab'
# 是否在桥接断开时关闭新创建的标签页,可选,默认 false
closeNewTabsAfterDisconnect: <boolean>
# 是否忽略 HTTPS 证书错误,可选,默认 false
acceptInsecureCerts: <boolean>
# 在调用 aiAction 时发送给 AI 模型的背景知识,可选
aiActionContext: <string>
android 部分
android:
# 设备 ID,可选,默认使用第一个连接的设备
deviceId: <device-id>
# 启动 URL,可选,默认使用设备当前页面
launch: <url>
# 输出 aiQuery/aiAssert 结果的 JSON 文件路径,可选
output: <path-to-output-file>
tasks 部分
tasks 部分是一个数组,定义了脚本执行的步骤。记得在每个步骤前添加 - 符号,表明这些步骤是个数组。
flow 部分的接口与 API几乎相同,除了一些参数的嵌套层级。
tasks:
- name: <name>
continueOnError: <boolean> # 可选,错误时是否继续执行下一个任务,默认 false
flow:
# 自动规划(Auto Planning, .ai)
# ----------------
# 执行一个交互,`ai` 是 `aiAction` 的简写方式
- ai: <prompt>
cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
# 这种用法与 `ai` 相同
- aiAction: <prompt>
cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
# 即时操作(Instant Action, .aiTap, .aiHover, .aiInput, .aiKeyboardPress, .aiScroll)
# ----------------
# 点击一个元素,用 prompt 描述元素位置
- aiTap: <prompt>
deepThink: <boolean> # 可选,是否使用深度思考(deepThink)来精确定位元素。默认值为 False
xpath: <xpath> # 可选,目标元素的 xpath 路径,用于执行当前操作。如果提供了这个 xpath,Midscene 会优先使用该 xpath 来找到元素,然后依次使用缓存和 AI 模型。默认值为空
cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
# 鼠标悬停一个元素,用 prompt 描述元素位置
- aiHover: <prompt>
deepThink: <boolean> # 可选,是否使用深度思考(deepThink)来精确定位元素。默认值为 False
xpath: <xpath> # 可选,目标元素的 xpath 路径,用于执行当前操作。如果提供了这个 xpath,Midscene 会优先使用该 xpath 来找到元素,然后依次使用缓存和 AI 模型。默认值为空
cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
# 输入文本到一个元素,用 prompt 描述元素位置
- aiInput: <输入框的最终文本内容>
locate: <prompt>
deepThink: <boolean> # 可选,是否使用深度思考(deepThink)来精确定位元素。默认值为 False
xpath: <xpath> # 可选,目标元素的 xpath 路径,用于执行当前操作。如果提供了这个 xpath,Midscene 会优先使用该 xpath 来找到元素,然后依次使用缓存和 AI 模型。默认值为空
cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
# 在元素上按下某个按键(如 Enter,Tab,Escape 等),用 prompt 描述元素位置
- aiKeyboardPress: <按键>
locate: <prompt>
deepThink: <boolean> # 可选,是否使用深度思考(deepThink)来精确定位元素。默认值为 False
xpath: <xpath> # 可选,目标元素的 xpath 路径,用于执行当前操作。如果提供了这个 xpath,Midscene 会优先使用该 xpath 来找到元素,然后依次使用缓存和 AI 模型。默认值为空
cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
# 全局滚动,或滚动 prompt 描述的元素
- aiScroll:
direction: 'up' # 或 'down' | 'left' | 'right'
scrollType: 'once' # 或 'untilTop' | 'untilBottom' | 'untilLeft' | 'untilRight'
distance: <number> # 可选,滚动距离,单位为像素
locate: <prompt> # 可选,执行滚动的元素
deepThink: <boolean> # 可选,是否使用深度思考(deepThink)来精确定位元素。默认值为 False
xpath: <xpath> # 可选,目标元素的 xpath 路径,用于执行当前操作。如果提供了这个 xpath,Midscene 会优先使用该 xpath 来找到元素,然后依次使用缓存和 AI 模型。默认值为空
cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
# 在报告文件中记录当前截图,并添加描述
- logScreenshot: <title> # 可选,截图的标题,如果未提供,则标题为 'untitled'
content: <content> # 可选,截图的描述
# 数据提取
# ----------------
# 执行一个查询,返回一个 JSON 对象
- aiQuery: <prompt> # 记得在提示词中描述输出结果的格式
name: <name> # 查询结果在 JSON 输出中的 key
# 更多 API
# ----------------
# 等待某个条件满足,并设置超时时间(ms,可选,默认 30000)
- aiWaitFor: <prompt>
timeout: <ms>
# 执行一个断言
- aiAssert: <prompt>
errorMessage: <error-message> # 可选,当断言失败时打印的错误信息。
name: <name> # 可选,给断言一个名称,会在 JSON 输出中作为 key 使用
# 等待一定时间
- sleep: <ms>
# 在 web 页面上下文中执行一段 JavaScript 代码
- javascript: <javascript>
name: <name> # 可选,给返回值一个名称,会在 JSON 输出中作为 key 使用
- name: <name>
flow:
# ...
二)使用 Chrome 插件的桥接模式

1. 配置 OpenAI API Key
# 更新为你自己的 Key
export OPENAI_API_KEY="sk-abcdefghijklmnopqrstuvwxyz"
2. 在 Chrome 应用商店安装 Midscene 浏览器插件
安装依赖
npm install @midscene/web tsx --save-dev
# or
yarn add @midscene/web tsx --save-dev
3. 编写脚本
编写并保存以下代码为 ./demo-new-tab.ts。
import { AgentOverChromeBridge } from "@midscene/web/bridge-mode";
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
Promise.resolve(
(async () => {
const agent = new AgentOverChromeBridge();
// 这个方法将连接到你的桌面 Chrome 的新标签页
// 记得启动你的 Chrome 插件,并点击 'allow connection' 按钮。否则你会得到一个 timeout 错误
await agent.connectNewTabWithUrl("https://www.bing.com");
// 这些方法与普通 Midscene agent 相同
await agent.ai('type "AI 101" and hit Enter');
await sleep(3000);
await agent.aiAssert("there are some search results");
await agent.destroy();
})()
);
4.启动 Chrome 插件

启动桌面 Chrome 和 Midscene 插件,并切换到 'Bridge Mode' 标签页。点击 "Allow connection"。
5. 运行脚本
三)集成到 Puppeteer
Puppeteer 是一个 Node.js 库,它通过 DevTools 协议或 WebDriver BiDi 提供控制 Chrome 或 Firefox 的高级 API。
Puppeteer 默认在无界面模式(headless)下运行,但可以配置为在可见的浏览器模式(headed)中运行。
1)配置 AI 模型服务
# 替换为你的 API Key
export OPENAI_API_KEY="sk-abcdefghijklmnopqrstuvwxyz"
# 可能需要更多配置,如模型名称、接入点等,请参考 《选择 AI 模型》文档
export OPENAI_BASE_URL="..."
2)安装依赖
yarn add @midscene/web puppeteer tsx --save-dev
# or
npm install @midscene/web puppeteer tsx --save-dev
3)编写脚本
编写下方代码,保存为 ./demo.ts
import puppeteer from "puppeteer";
import { PuppeteerAgent } from "@midscene/web/puppeteer";
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
Promise.resolve(
(async () => {
const browser = await puppeteer.launch({
headless: false, // here we use headed mode to help debug
});
const page = await browser.newPage();
await page.setViewport({
width: 1280,
height: 800,
deviceScaleFactor: 1,
});
await page.goto("https://www.ebay.com");
await sleep(5000);
// 👀 初始化 Midscene agent
const agent = new PuppeteerAgent(page);
// 👀 执行搜索
// 注:尽管这是一个英文页面,你也可以用中文指令控制它
await agent.aiAction('在搜索框输入 "Headphones" ,敲回车');
await sleep(5000);
// 👀 理解页面,提取数据
const items = await agent.aiQuery(
'{itemTitle: string, price: Number}[], 找到列表里的商品标题和价格',
);
console.log("耳机商品信息", items);
// 👀 用 AI 断言
await agent.aiAssert("界面左侧有类目筛选功能");
await browser.close();
})()
);
4)运行
使用 tsx 来运行,你会看到命令行打印出了耳机的商品信息:
# run
npx tsx demo.ts
# 命令行应该有如下输出
# [
# {
# itemTitle: 'Beats by Dr. Dre Studio Buds Totally Wireless Noise Cancelling In Ear + OPEN BOX',
# price: 505.15
# },
# {
# itemTitle: 'Skullcandy Indy Truly Wireless Earbuds-Headphones Green Mint',
# price: 186.69
# }
# ]
5)查看运行报告
当上面的命令执行成功后,会在控制台输出:Midscene - report file updated: /path/to/report/some_id.html, 通过浏览器打开该文件即可看到报告。
四)集成到 Playwright
Playwright.js 是由微软开发的一个开源自动化库,主要用于对网络应用程序进行端到端测试(end-to-end test)和网页抓取。
与 Playwright 的集成方式有以下两种方式:
- 直接用脚本方式集成和调用 Midscene Agent,适合快速体验、原型开发、数据抓取和自动化脚本等场景。
- 在 Playwright 的测试用例中集成 Midscene,适合需要执行 UI 测试的场景。
1)配置 AI 模型服务
# 替换为你的 API Key
export OPENAI_API_KEY="sk-abcdefghijklmnopqrstuvwxyz"
# 可能需要更多配置,如模型名称、接入点等,请参考 《选择 AI 模型》文档
export OPENAI_BASE_URL="..."
2)安装依赖
npm install @midscene/web playwright @playwright/test tsx --save-dev
# or
yarn add @midscene/web playwright @playwright/test tsx --save-dev
3)编写脚本
编写下方代码,保存为 ./demo.ts
import { chromium } from 'playwright';
import { PlaywrightAgent } from '@midscene/web/playwright';
import 'dotenv/config'; // read environment variables from .env file
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
Promise.resolve(
(async () => {
const browser = await chromium.launch({
headless: true, // 'true' means we can't see the browser window
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
const page = await browser.newPage();
await page.setViewportSize({
width: 1280,
height: 768,
});
await page.goto('https://www.ebay.com');
await sleep(5000); // 👀 init Midscene agent
const agent = new PlaywrightAgent(page);
// 👀 type keywords, perform a search
await agent.aiAction('type "Headphones" in search box, hit Enter');
// 👀 wait for the loading
await agent.aiWaitFor('there is at least one headphone item on page');
// or you may use a plain sleep:
// await sleep(5000);
// 👀 understand the page content, find the items
const items = await agent.aiQuery(
'{itemTitle: string, price: Number}[], find item in list and corresponding price',
);
console.log('headphones in stock', items);
const isMoreThan1000 = await agent.aiBoolean(
'Is the price of the headphones more than 1000?',
);
console.log('isMoreThan1000', isMoreThan1000);
const price = await agent.aiNumber(
'What is the price of the first headphone?',
);
console.log('price', price);
const name = await agent.aiString(
'What is the name of the first headphone?',
);
console.log('name', name);
const location = await agent.aiLocate(
'What is the location of the first headphone?',
);
console.log('location', location);
// 👀 assert by AI
await agent.aiAssert('There is a category filter on the left');
// 👀 click on the first item
await agent.aiTap('the first item in the list');
await browser.close();
})(),
);
4)运行
使用 tsx 来运行,你会看到命令行打印出了耳机的商品信息:
# run
npx tsx demo.ts
# 命令行应该有如下输出
# [
# {
# itemTitle: 'JBL Tour Pro 2 - True wireless Noise Cancelling earbuds with Smart Charging Case',
# price: 551.21
# },
# {
# itemTitle: 'Soundcore Space One无线耳机40H ANC播放时间2XStronger语音还原',
# price: 543.94
# }
# ]
5) 查看运行报告
当上面的命令执行成功后,会在控制台输出:Midscene - report file updated: /path/to/report/some_id.html, 通过浏览器打开该文件即可看到报告。