🌐在人工智能 Agent 日益普及的今天,模型不再只是聊天工具,而是能够主动执行任务、操作外部系统、获取并处理真实世界数据的“数字员工”。这种能力的核心支撑之一,就是 MCP(Model Context Protocol,模型上下文协议) 。本文将深入剖析 MCP 的概念,并结合 Playwright 浏览器自动化工具,通过两个完整的实战案例——掘金插件页面测试 与 Trae AI 产品信息抓取,全面展示如何利用 MCP 构建强大的 AI Agent。
🔧 什么是 MCP(Model Context Protocol)?
MCP 并非一个具体的软件库,而是一种通信协议规范。它定义了大型语言模型(LLM)如何与外部工具(Tools)进行标准化交互。
-
核心思想:模型本身不具备直接操作文件系统、数据库或浏览器的能力。MCP 充当“翻译官”和“调度员”,将模型的自然语言指令转化为对特定工具的结构化调用(如 JSON-RPC),并将工具的执行结果以模型能理解的格式返回。
-
关键组件:
- 模型(Model) :发出指令的 AI 大脑。
- MCP Server:运行在本地或云端的服务,负责管理一个或多个工具。
- 工具(Tool) :执行具体任务的程序,例如
playwright工具可以控制浏览器。
-
工作流程:
- 用户向模型提出请求(如“帮我抓取 trae.ai 的产品信息”)。
- 模型识别出需要使用
playwright工具,并生成一个符合 MCP 协议的函数调用请求。 - MCP Server 接收到请求,调用对应的
playwright工具。 playwright工具执行浏览器自动化脚本,完成抓取任务。- 工具将结果(如网页标题、价格文本)返回给 MCP Server。
- MCP Server 将结果封装后返回给模型。
- 模型基于这些真实数据,生成最终的回答呈现给用户。
这种方式彻底改变了传统 AI 的被动问答模式,使其具备了主动感知和改造数字世界的能力。
🤖 Playwright:现代 Web 自动化的利器
Playwright 是由 Microsoft 开源的 Node.js 库,用于跨浏览器(Chromium, Firefox, WebKit)的端到端测试和自动化。它以其速度、可靠性和强大的功能集(如自动等待、网络拦截、设备模拟等)而闻名。
在 MCP 生态中,@playwright/mcp 是一个官方提供的 MCP 工具包,它将 Playwright 的 API 封装成一系列可通过 MCP 协议调用的函数,例如:
mcp_Playwright_playwright_navigate: 导航到指定 URL。mcp_Playwright_playwright_evaluate: 在浏览器上下文中执行 JavaScript 代码并返回结果。mcp_Playwright_playwright_close: 关闭浏览器。
这使得 AI 模型无需了解 Playwright 的底层细节,只需通过自然语言描述意图,即可驱动浏览器完成复杂操作。
📌 实战一:掘金(Juejin)插件页面自动化测试
第一个案例展示了如何使用原生 Playwright 脚本对国内知名开发者社区“掘金”进行简单的 UI 测试。该脚本位于 test-juejin-plugin.js 文件中。
🧪 脚本目标
- 打开掘金首页。
- 点击顶部导航栏的“插件”按钮。
- 等待新页面加载完成。
- 对整个插件页面进行截图。
- 验证页面内容是否包含“插件”关键词。
📜 代码详解
const { chromium } = require('playwright');
async function testJuejinPlugin() {
// 启动 Chromium 浏览器,非无头模式(headless: false)以便观察过程
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
// 1. 访问掘金网站,并等待网络空闲(确保所有资源加载完毕)
console.log('正在访问掘金网站...');
await page.goto('https://juejin.cn/', { waitUntil: 'networkidle' });
// 2. 使用文本选择器精准点击“插件”按钮
console.log('正在点击插件按钮...');
await page.click('text=插件');
// 3. 再次等待新页面网络空闲
console.log('等待插件页面加载完成...');
await page.waitForLoadState('networkidle');
// 4. 截取完整页面并保存为 'juejin-plugin-page.png'
console.log('正在截图...');
const screenshotPath = 'juejin-plugin-page.png';
await page.screenshot({ path: screenshotPath, fullPage: true });
console.log(`截图已保存到: ${screenshotPath}`);
// 5. 获取页面完整 HTML 内容,并检查是否包含“插件”文本
console.log('正在检查页面内容...');
const pageContent = await page.content();
if (pageContent.includes('插件')) {
console.log('✅ 页面包含插件相关内容');
} else {
console.log('❌ 页面不包含插件相关内容');
}
} catch (error) {
console.error('测试过程中发生错误:', error);
} finally {
// 无论成功与否,都确保关闭浏览器释放资源
await browser.close();
console.log('测试完成');
}
}
// 执行测试函数
testJuejinPlugin();
这个脚本虽然简单,但体现了自动化测试的核心要素:操作、等待、断言、清理。它是理解更复杂自动化任务的基础。
📌 实战二:Trae AI 产品信息抓取(双版本实现)
第二个案例更为复杂,目标是从 https://www.trae.ai/ 抓取产品的名称、价格、特点和优势,并将结果整理成表格。有趣的是,我们拥有两个版本的实现:一个使用原生 Playwright (scrape-trae.js),另一个则专门为 MCP 环境设计 (scrape-trae-mcp.js)。
🎯 抓取目标分析
- 产品名称:通常可以从
<title>标签获取。 - 价格信息:需要在页面中寻找包含
$、免费或Free等关键词的元素,这些元素的 class 通常包含price字样。 - 特点和优势:一般位于带有
<h2>或<h3>标题的<section>区块中,其下的<p>标签包含详细描述。
📜 原生 Playwright 版本 (scrape-trae.js)
此版本与掘金测试脚本类似,直接使用 Playwright API。
// ... [启动浏览器、设置超时等]
// 提取产品名称
const productName = await page.title();
// 提取特点和优势:遍历所有 <section>,查找其中的标题和段落
const features = [];
const featureSections = await page.$$('section');
for (const section of featureSections) {
const title = await section.$('h2, h3');
if (title) {
const titleText = await title.textContent();
const content = await section.$('p');
const contentText = content ? await content.textContent() : '';
features.push({ title: titleText.trim(), content: contentText.trim() });
}
}
// 提取价格信息:在浏览器上下文中执行自定义 JS
const priceInfo = await page.evaluate(() => {
const priceElements = document.querySelectorAll('div[class*="price"], span[class*="price"], h3[class*="price"]');
const prices = [];
priceElements.forEach(el => {
const priceText = el.textContent().trim();
if (priceText && (priceText.includes('$') || priceText.includes('免费') || priceText.includes('Free'))) {
prices.push(priceText);
}
});
return prices;
});
// ... [输出结果、生成表格、关闭浏览器]
📜 MCP 专用版本 (scrape-trae-mcp.js)
此版本完全遵循 MCP 协议,所有的浏览器操作都通过 mcp_Playwright_... 函数调用完成。
// 1. 导航到网站
await mcp_Playwright_playwright_navigate({
url: 'https://www.trae.ai/',
waitUntil: 'load',
timeout: 60000
});
// 2. 确保页面加载完成(通过执行 JS 检查 readyState)
await mcp_Playwright_playwright_evaluate({
script: 'return document.readyState === "complete"'
});
// 3. 提取产品名称(通过获取 document.title)
const productName = await mcp_Playwright_playwright_evaluate({
script: 'return document.title'
});
// 4. 提取价格和特点:同样是通过在页面上下文中执行复杂的 JS 脚本来实现
const priceInfo = await mcp_Playwright_playwright_evaluate({
script: `...` // 与原生版本中的 evaluate 脚本逻辑一致
});
const features = await mcp_Playwright_playwright_evaluate({
script: `...` // 与原生版本中的 evaluate 脚本逻辑一致
});
// ... [后续的输出和表格生成逻辑完全相同]
🔍 两个版本的关键区别
| 特性 | 原生 Playwright (scrape-trae.js) | MCP Playwright (scrape-trae-mcp.js) |
|---|---|---|
| 执行环境 | 直接在 Node.js 中运行 | 由 MCP Server 调用,在 MCP 上下文中运行 |
| API 调用 | page.goto(), page.evaluate() | mcp_Playwright_playwright_navigate(), mcp_Playwright_playwright_evaluate() |
| 适用场景 | 独立脚本、CI/CD 流水线 | 作为 AI Agent 的工具,响应模型指令 |
| 依赖 | playwright | 由 MCP Server 提供,脚本本身不直接依赖 |
这两个脚本的存在,完美地展示了同一项任务如何根据不同的执行上下文(独立脚本 vs. AI Agent 工具)进行适配。
📦 项目依赖与配置
项目的依赖关系由 package.json 和 package-lock.json 精确定义。
-
package.json:{ "dependencies": { "@playwright/test": "^1.57.0" } }这里指定了项目依赖
@playwright/test,这是一个包含了 Playwright 核心功能的包,用于编写和运行测试。 -
package-lock.json:
这个文件锁定了确切的依赖版本,确保在任何环境下安装的都是完全相同的代码。从中可以看到,最终安装的是playwright@1.57.0,它又依赖于playwright-core@1.57.0。
对于 MCP 的使用,readme.md 提供了关键的配置步骤:
-
在 Trae AI 的设置中配置 MCP Server:
{"mcpServers": {"playwright": {"command": "npx","args": ["-y", "@playwright/mcp@latest"]}}} -
在终端手动启动 MCP Server(用于调试):
npx -y @playwright/mcp@latest
📝 总结:AI Agent 的未来已来
通过以上详尽的分析,我们可以清晰地看到一条技术演进的脉络:
- 基础能力:Playwright 提供了强大而可靠的浏览器自动化能力。
- 协议抽象:MCP 协议将这种能力封装成标准化的工具接口。
- 智能集成:AI 模型通过 MCP 调用这些工具,从而获得了“手”和“眼”,能够主动探索和操作互联网。
从测试一个简单的“插件”按钮,到抓取并结构化一个 AI 创业公司的产品信息,这些案例不仅仅是代码示例,更是下一代人机交互范式的缩影。未来的 AI 不再是信息的被动提供者,而是任务的主动执行者。而 MCP + Playwright 的组合,正是构建这类智能体的关键基石之一。🚀