



01
LLM能力跃升:三年前的浏览器自动化主要靠脚本,页面改个按钮文案就挂。现在的LLM能理解上下文,它不只是"按规则执行",而是能"理解页面、做出判断、动态调整"。
企业级产品成熟:Amazon Bedrock AgentCore、OpenAI Atlas、Google Chrome Auto Browse这些产品已经从"预览"进入"全面生产"。Gartner预测,到2026年底,40%的企业应用会内置任务特定的AI智能体。
MCP协议打通生态:AI Agent能控制浏览器,关键在于"连接标准"。MCP解决了这个问题——一个协议,定义Agent如何调用外部工具和数据。OpenAI、Google、AWS全部采纳,生态快速扩张。
02
03
# 安装Playwright
npm init -y
npm install playwright @playwright/test
# 安装浏览器
npx playwright install chromium# 启动Playwright MCP Server
npx @playwright/mcp-server start --port 3100
# 或者使用Python版本
pip install playwright
python -m playwright mcp-server start --port 3100// mcp-server.ts
import { chromium } from 'playwright';
import { createServer } from 'http';
import { parse } from 'url';
// MCP Server核心实现
const BROWSER_TOOLS = {
navigate: {
description: 'Navigate to a URL',
params: ['url'],
handler: async (page, { url }) => {
await page.goto(url);
return { success: true, title: await page.title(), url: page.url() };
}
},
click: {
description: 'Click an element',
params: ['selector'],
handler: async (page, { selector }) => {
await page.click(selector);
return { success: true };
}
},
fill: {
description: 'Fill input field',
params: ['selector', 'text'],
handler: async (page, { selector, text }) => {
await page.fill(selector, text);
return { success: true };
}
},
screenshot: {
description: 'Take screenshot',
params: ['path', 'fullPage'],
handler: async (page, { path, fullPage = false }) => {
await page.screenshot({ path, fullPage });
return { path };
}
},
extractText: {
description: 'Extract text content',
params: ['selector'],
handler: async (page, { selector }) => {
return { text: await page.textContent(selector) };
}
},
waitForSelector: {
description: 'Wait for element to appear',
params: ['selector', 'timeout'],
handler: async (page, { selector, timeout = 30000 }) => {
await page.waitForSelector(selector, { timeout });
return { found: true };
}
},
evaluate: {
description: 'Run JavaScript in page',
params: ['script'],
handler: async (page, { script }) => {
return { result: await page.evaluate(script) };
}
}
};
async function main() {
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext();
const page = await context.newPage();
// 启动HTTP服务,暴露MCP接口
const server = createServer(async (req, res) => {
if (req.method === 'POST') {
let body = '';
req.on('data', chunk => body += chunk);
req.on('end', async () => {
const { tool, params } = JSON.parse(body);
if (BROWSER_TOOLS[tool]) {
const result = await BROWSER_TOOLS[tool].handler(page, params);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(result));
} else {
res.writeHead(404);
res.end(JSON.stringify({ error: 'Tool not found' }));
}
});
} else {
// 返回可用工具列表
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
tools: Object.entries(BROWSER_TOOLS).map(([name, config]) => ({
name,
description: config.description,
params: config.params
}))
}));
}
});
server.listen(3100);
console.log('Playwright MCP Server running on http://localhost:3100');
}
main().catch(console.error);{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["@playwright/mcp-server", "start", "--port", "3100"],
"env": {}
}
}
}{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["@playwright/mcp-server", "start", "--port", "3100"]
}
}
}

`navigate`→ 打开商城 `click`→ 进入分类 `fill`→ 输入筛选条件 `evaluate`→ 提取商品数据(复杂提取用JS更灵活) `screenshot`→ 保存结果截图
// tests/mcp-ai-test.spec.ts
import { test, expect } from '@playwright/test';
test.describe('AI-assisted E2E Testing with MCP', () => {
test('智能数据采集流程', async ({ page }) => {
// MCP Server暴露的工具可以直接在测试中调用
const mcpTools = await initMcpTools(page);
// Step 1: 导航到目标页面
await mcpTools.navigate('https://example-shop.com/laptops');
// Step 2: AI分析页面结构(通过截图)
await mcpTools.screenshot({ path: './debug/initial-page.png' });
const analysis = await ai.analyzeScreenshot(`
分析这个电商列表页,找出:
1. 商品名称的选择器
2. 价格的选择器
3. "加入购物车"按钮的位置
`);
// Step 3: 执行AI生成的操作序列
const products = await mcpTools.evaluate({
script: `
return Array.from(document.querySelectorAll('.product-item'))
.slice(0, 10)
.map(item => ({
name: item.querySelector('.product-name')?.textContent,
price: item.querySelector('.product-price')?.textContent
}))
`
});
// Step 4: 验证结果
expect(products.length).toBeGreaterThanOrEqual(10);
console.log('采集到的商品数据:', products);
// Step 5: 截图留存
await mcpTools.screenshot({ path: './debug/products-collected.png', fullPage: true });
});
test('AI辅助的异常检测', async ({ page }) => {
await mcpTools.navigate('https://example-shop.com/checkout');
// 故意触发异常场景
await mcpTools.click({ selector: '#submit-order' });
// 截图并让AI分析
await mcpTools.screenshot({ path: './debug/error-state.png' });
const errorAnalysis = await ai.analyzeScreenshot(`
分析这个错误页面:
1. 错误类型是什么
2. 错误消息内容
3. 建议的修复方向
`);
console.log('AI分析结果:', errorAnalysis);
expect(errorAnalysis.errorType).toBeDefined();
});
});04
05
构建MCP Server:把你项目的测试能力封装成MCP Server,AI Agent可以直接调用你的自动化能力
比如封装"登录→进入后台→执行操作"这个固定流程
比如封装"截图→AI分析→返回结果"这套分析链路
用Playwright录制Trace
用AI分析失败原因
用MCP让AI能"操作"测试环境
竞品价格监控
内容批量采集
运营报表自动生成
06
class BrowserSessionPool {
private sessions: Map= new Map();
private idleTimeouts: Map= new Map();
async getSession(sessionId: string): Promise{
if (!this.sessions.has(sessionId)) {
const browser = await chromium.launch();
const context = await browser.newContext();
this.sessions.set(sessionId, context);
}
// 重置idle超时
this.resetIdleTimeout(sessionId);
return this.sessions.get(sessionId)!;
}
async closeSession(sessionId: string) {
const context = this.sessions.get(sessionId);
if (context) {
await context.close();
this.sessions.delete(sessionId);
}
}
private resetIdleTimeout(sessionId: string, ttl = 300000) {
const existing = this.idleTimeouts.get(sessionId);
if (existing) clearTimeout(existing);
this.idleTimeouts.set(sessionId, setTimeout(async () => {
await this.closeSession(sessionId);
}, ttl));
}
}async function withRetry(
fn: () => Promise,
options = { retries: 3, delay: 1000 }
): Promise{
for (let i = 0; i < options.retries; i++) {
try {
return await fn();
} catch (error) {
if (i === options.retries - 1) throw error;
console.log(`Attempt ${i + 1} failed, retrying...`);
await new Promise(r => setTimeout(r, options.delay));
options.delay *= 2;
}
}
throw new Error('Should not reach here');
}
// 使用示例
await withRetry(async () => {
await page.click('#submit-btn', { timeout: 5000 });
});const AUTHORIZED_TOOLS = ['navigate', 'screenshot', 'extractText', 'evaluate'];
const BLOCKED_DOMAINS = ['bank.com', 'admin.internal'];
async function validateRequest(tool: string, params: any) {
if (!AUTHORIZED_TOOLS.includes(tool)) {
throw new Error(`Tool ${tool} is not authorized`);
}
if (tool === 'navigate') {
const url = new URL(params.url);
if (BLOCKED_DOMAINS.some(d => url.hostname.includes(d))) {
throw new Error(`Domain ${url.hostname} is blocked`);
}
}
return true;
}07
MCP不会一统天下,但会成主流标准之一USB-C之前也有各种私有协议,最终还是被统一了。MCP现在处境类似。Google同时在推A2A(Agent to Agent),这两个协议解决的是不同层面的问题,未来大概率会共存。 测试工程师的价值锚点在转移以前的价值锚点是"你会多少工具",未来是"你能为AI提供多少可信赖的执行能力"。会写Playwright脚本的人很多,但能构建AI可调用的测试服务的人很少。 浏览器自动化会越来越"智能"
08
09
夜雨聆风