
1. 为什么我放弃了纯脚本转向 Playwright MCP 做 UI 自动化测试UI 自动化测试最让人头疼的不是写脚本而是页面一改选择器就全废。我维护过一套两百多条用例的 Playwright 脚本前端一次组件重构#login-btn变成[data-testidsubmit]一晚上红了四十条。后来我把 Playwright 和 MCP 协议接起来用自然语言驱动浏览器选择器由模型根据页面快照动态推断维护成本直接砍半。Playwright MCP 到底是什么一句话它把 Playwright 的浏览器控制能力封装成 MCP 工具让大模型能通过标准协议调用「打开页面、点击、填表单、截图、取文本」这些动作。你不再手写每一步 API而是描述意图模型拆解成工具调用序列去执行。适合谁三类人最受益一是测试工程师想快速搭端到端流程二是前端/全栈想给自己项目加冒烟测试但不想学完整测试框架三是做 AI Agent 的开发者需要一个能操作真实浏览器的「手」。它和传统脚本不是替代关系。稳定的核心用例我仍然用纯 Playwright 脚本跑 CI而探索性测试、频繁变动的页面、临时验证需求交给 MCP 对话式执行。两者配合才是当前最务实的落地路径。下面从环境搭建讲到第一个用例跑通配置片段都能直接复制。2. 环境准备Playwright 驱动安装与 MCP 服务接入的完整配置先说清楚整体链路你的 MCP 客户端比如 Claude Desktop、Cline、Cursor 或 VSCode 插件负责发起对话MCP 服务进程负责把对话转成 Playwright 调用Playwright 再驱动真实浏览器。所以三样东西缺一不可Node 运行时、Playwright 浏览器驱动、MCP 服务配置。第一步确认 Node 版本。Playwright MCP 官方包要求 Node 18 以上我实测 20 LTS 最稳node -v # 期望输出 v20.x.x 或更高 npm -v如果版本太低用 nvm 切一下。Windows 用户直接去官网下 LTS 安装包即可不涉及任何网络工具。第二步安装 Playwright 浏览器驱动。MCP 服务底层还是调 Playwright所以浏览器二进制必须先装好。全局装一次就够npm install -g playwright npx playwright install chromium只装 chromium 能覆盖绝大多数场景需要 Firefox 或 WebKit 再单独npx playwright install firefox。国内下载慢的话设置镜像环境变量再装# Linux / macOS export PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright npx playwright install chromium# Windows PowerShell $env:PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright npx playwright install chromium第三步接入 MCP 服务。官方包playwright/mcp用 npx 直接拉起不用全局安装。以 Cline / VSCode 系的 MCP 配置为例在客户端的 MCP 设置文件里加{ mcpServers: { playwright: { command: npx, args: [-y, playwright/mcplatest, --headless], env: { PLAYWRIGHT_DOWNLOAD_HOST: https://npmmirror.com/mirrors/playwright }, timeout: 300 } } }这里三个关键点-y让 npx 自动确认安装--headless让浏览器无头运行调试阶段可以去掉肉眼看它点timeout给足 300 秒首次启动要下依赖会慢。Claude Desktop 的配置路径在claude_desktop_config.json结构完全一样把上面这段塞进mcpServers即可。如果你用的是支持远程模型的客户端想让模型侧也统一走一个入口可以把模型服务地址配成 TaoToken 的 API 地址https://taotoken.net/apiKey 在控制台生成。这样 MCP 客户端调模型、模型调 MCP 工具链路清晰。生成 Key 的入口在 TaoToken API Keys接入细节看 TaoToken 接入文档。配置保存后重启客户端在 MCP 面板里应该能看到playwright服务处于 connected 状态工具列表里出现browser_navigate、browser_click、browser_type、browser_snapshot这些。看到它们说明服务接入成功。3. 可复制配置MCP 服务参数、浏览器驱动与首个测试用例脚本这一节给你三份能直接用的东西MCP 服务完整配置、Playwright 测试脚本、以及一个把两者串起来的目录结构。先看 MCP 服务的完整参数配置。官方playwright/mcp支持不少启动参数常用的我列成表方便你按需改参数作用推荐值--headless无头模式运行调试时去掉--browser指定浏览器chromium--viewport-size视口尺寸1280,720--device模拟移动设备iPhone 15--save-trace保存 trace 便于回放排障时开--isolated每次会话独立上下文测试隔离建议开把这些拼进配置{ mcpServers: { playwright: { command: npx, args: [ -y, playwright/mcplatest, --browser, chromium, --viewport-size, 1280,720, --isolated, --save-trace ], timeout: 300 } } }--isolated很关键它保证每次对话都是干净的浏览器上下文不会因为上一次的 cookie 污染这次测试。--save-trace会在工作目录生成 trace 文件用例失败时用npx playwright show-trace trace.zip能一步步回放定位问题比看日志快十倍。接着是纯 Playwright 测试脚本作为对照和 CI 用。建一个tests/login.spec.tsimport { test, expect } from playwright/test; test(登录流程端到端验证, async ({ page }) { await page.goto(https://example.com/login); await page.getByLabel(用户名).fill(testuser); await page.getByLabel(密码).fill(testpass); await page.getByRole(button, { name: 登录 }).click(); await expect(page.locator(.dashboard)).toBeVisible({ timeout: 10000 }); await expect(page).toHaveTitle(/Dashboard/); await page.getByRole(button, { name: 退出 }).click(); await expect(page.locator(.login-form)).toBeVisible(); });注意我用了getByLabel、getByRole这类语义化定位器而不是#username。这是 Playwright 官方推荐的首选策略页面结构变动时存活率远高于 CSS 选择器。配套的playwright.config.tsimport { defineConfig } from playwright/test; export default defineConfig({ testDir: ./tests, timeout: 30000, retries: 1, use: { baseURL: https://example.com, headless: true, trace: on-first-retry, screenshot: only-on-failure, }, });retries: 1加trace: on-first-retry是我踩过坑后的固定搭配偶发失败自动重试一次重试时留 trace既不误报又能复盘。目录结构建议这样组织MCP 配置和测试脚本分开project/ ├── .mcp/ │ └── settings.json # MCP 服务配置 ├── tests/ │ └── login.spec.ts # Playwright 用例 ├── playwright.config.ts └── package.json装依赖npm init -y npm install -D playwright/test npx playwright install chromium到这里配置和脚本都齐了。MCP 负责对话式探索Playwright 脚本负责稳定回归两者共用同一套浏览器驱动不冲突。4. 验证请求本地跑通 MCP 对话式测试与脚本执行的成功结果配置写完必须验证否则你不知道是 MCP 没连上还是浏览器没装好。分两条路验证先验纯脚本再验 MCP 对话。先跑脚本确认 Playwright 本身没问题npx playwright test tests/login.spec.ts --headed--headed让你看到浏览器真的打开、输入、点击。成功的话终端输出类似Running 1 test using 1 worker 1 passed (3.2s)如果这一步就失败问题在 Playwright 层跟 MCP 无关先解决它。常见的是浏览器没装或版本不匹配npx playwright install --force chromium重装即可。脚本通过后验证 MCP 对话式执行。打开你的 MCP 客户端新建对话输入这样一段自然语言打开 https://example.com/login在用户名输入框填 testuser密码框填 testpass点击登录按钮等 dashboard 出现后告诉我页面标题然后点退出。模型会依次调用browser_navigate、browser_snapshot拿页面结构、browser_type、browser_click等工具。你会在客户端里看到工具调用日志类似[tool] browser_navigate { url: https://example.com/login } [tool] browser_snapshot {} [tool] browser_type { element: 用户名输入框, text: testuser } [tool] browser_click { element: 登录按钮 } [tool] browser_snapshot {}最后模型返回「页面标题是 Dashboard - Example已点击退出当前回到登录页。」这就说明整条链路通了客户端 → MCP 服务 → Playwright → 浏览器 → 回传结果。我实测下来首次对话因为要下依赖会慢十几秒之后每次操作响应在 1-3 秒。如果模型说「找不到元素」别急着改配置先让它调一次browser_snapshot把当前页面结构打出来多半是页面还没加载完或元素在 iframe 里。验证阶段还有个技巧让模型执行一段 JS 确认页面状态。比如在当前页面执行 document.title 并返回结果。模型会调browser_evaluate返回真实标题。这比截图更直接适合做断言。两条路都跑通你的 Playwright MCP 环境就算真正可用了。5. 常见报错排查从 401 到 local proxy failed 的对照解决这一节按真实报错来每条都给你现象、原因、解法。报错一401 Unauthorized。现象是 MCP 客户端连模型时返回 401。原因通常是 API Key 没配、配错或过期。如果你用的是 TaoToken 这类统一入口检查客户端里模型服务的 Base URL 是否为https://taotoken.net/apiKey 是否从控制台正确复制注意别带多余空格。重新生成一个 Key 再试入口在 API Keys 页面。401 跟 Playwright 无关是模型侧鉴权问题别去折腾浏览器。报错二local proxy failed / connection refused。现象是 MCP 服务启动失败日志里出现连接被拒。原因多是 npx 拉包时网络中断或端口被占。解法先手动在终端跑一遍npx -y playwright/mcplatest --headless看它能不能独立启动。如果卡在下载配 npm 镜像npm config set registry https://registry.npmmirror.com然后清缓存重试npm cache clean --force。能独立启动后再回到客户端配置问题基本消失。报错三reading choices of undefined。这是模型返回结构解析失败通常出现在客户端和模型 API 格式不匹配时。检查你的客户端是否按 OpenAI 兼容格式配置Base URL 结尾不要多加/v1之外的路径。如果客户端支持自定义模型确认 Model ID 填的是服务端真实存在的模型名填错会导致返回体为空进而报 choices undefined。报错四OAuth / 授权回调失败。部分客户端首次连接需要 OAuth 流程。现象是浏览器弹出授权页但回调卡住。解法确认回调地址与客户端配置一致本地端口没被防火墙拦。如果客户端支持 API Key 直连优先用 Key 方式跳过 OAuth链路更短更稳。报错五浏览器启动即崩溃。现象是 MCP 日志里 chromium 进程秒退。Linux 上常见是缺系统依赖npx playwright install-deps chromium这条命令会自动装齐 libnss3、libatk 等库。Docker 环境里要在镜像构建阶段就执行它别等到运行时。报错六元素定位超时。现象是模型反复说找不到元素。先让它browser_snapshot看结构确认元素是否在 iframe 或 shadow DOM 里。iframe 需要先切上下文shadow DOM 要用 Playwright 的穿透定位。另外把默认超时调大在 MCP 配置里加--timeout 15000给动态加载留时间。排查顺序记住一条先确认 Playwright 脚本能跑再确认 MCP 服务能独立启动最后才查客户端配置。从下往上排能省一半时间。6. 从对话到回归把 MCP 探索结果沉淀成稳定用例MCP 对话式执行最大的价值不是替代脚本而是加速「探索 → 固化」这个循环。我的做法是新页面先用 MCP 对话跑一遍让模型把操作路径和元素定位吐出来我再把它翻译成 Playwright 脚本进 CI。具体怎么沉淀对话跑通后让模型输出对应的 Playwright 代码把刚才的登录操作转换成 Playwright TypeScript 测试代码用语义化定位器。模型会给出接近第 3 节那样的脚本你复制进tests/目录跑一遍npx playwright test验证通过就纳入回归集。这样探索阶段靠对话提速回归阶段靠脚本保稳两边优势都吃到。长期跑自动化建议把 Coding Plan 用起来让模型持续帮你维护用例、根据失败 trace 提修复建议。入口在 TaoToken Coding Plan。想先纯对话验证模型能力用 模型对话 试几条指令即可。控制台在 consoleKey 管理在 api-keys。最后给个实用技巧给 MCP 服务单独建一个工作目录--save-trace的产物、截图、下载文件都落在那里别和项目源码混在一起。CI 里跑纯脚本本地探索用 MCP两套配置共用同一个npx playwright install装好的浏览器互不干扰。跑通第一条用例后你会发现 UI 自动化的门槛比想象中低很多。