Puppeteer Accessibility Tree MCP Server:将DOM树翻译为LLM可读结构,提升AI Agent网页理解能力

LLM读不懂网页?试试把DOM树“翻译”成它能懂的语言
想让AI Agent自动填表、抓数据,结果它对着截图一脸懵,或者被几千行HTML代码直接搞晕?
问题不在LLM,在于你喂给它的“食物”不对。截图信息密度太低,原始HTML噪音又太多。我们需要一个“翻译官”,把网页翻译成LLM能高效理解的结构化语言。
这就是 Puppeteer Accessibility Tree MCP Server 干的事。它不是又一个浏览器自动化工具,而是一个专门为LLM设计的网页结构翻译器。
核心原理:从“看见”到“理解”
传统方案要么给LLM一张截图(视觉模式),要么给它原始HTML。前者依赖多模态能力,成本高、精度有限;后者Token消耗巨大,且充斥着<div>、<span>等对理解任务毫无帮助的标签噪音。
这个MCP Server走了第三条路:提取网页的可访问性树(Accessibility Tree)。
你可以把它理解为浏览器内部为屏幕阅读器等辅助技术构建的“网页骨架”。它只保留有语义的节点(如按钮、输入框、标题、链接),并以清晰的父子层级关系组织起来。
技术栈一目了然:
- Puppeteer 控制无头浏览器,打开目标网页。
- 通过Chrome DevTools Protocol (CDP) 调用
Accessibility.getFullAXTree命令。 - 将获取到的、原生的可访问性树数据,进行过滤、简化和格式化。
- 输出一份精炼的、JSON格式的“网页语义地图”,直接作为上下文喂给LLM。
// 核心逻辑示意(非完整代码)
const client = await page.target().createCDPSession();
const { nodes } = await client.send('Accessibility.getFullAXTree');
// 过滤和简化:只保留关键信息
const simplifiedTree = nodes.map(node => ({
role: node.role.value, // 如 'button', 'textbox', 'heading'
name: node.name.value, // 如 '登录', '搜索', '标题文本'
value: node.value?.value,
description: node.description?.value,
states: node.states, // 如 ['focused', 'disabled']
children: node.childIds // 保留层级关系
}));输出给LLM的,可能是这样的结构:
{
"role": "WebArea",
"name": "登录页面",
"children": [
{
"role": "textbox",
"name": "邮箱地址",
"states": ["required"]
},
{
"role": "textbox",
"name": "密码",
"states": ["required"]
},
{
"role": "button",
"name": "登录"
}
]
}技术价值:为Agent自动化“降本增效”
这套方案带来的优势是实实在在的:
1. Token成本断崖式下降
一份复杂的电商商品页,原始HTML可能有数万Token。而经过提炼的可访问性树,可能只需要几百Token就能精准描述“有一个价格筛选滑块、一个‘加入购物车’按钮、一个商品评论列表”。这直接降低了API调用成本,让Agent能处理更长的任务流。
2. 任务理解精度飙升
LLM拿到的是清晰的“角色-名称”语义对。当你说“点击登录按钮”时,它不再需要从一堆<div class="btn btn-primary">中猜测,而是直接定位到 role: "button", name: "登录" 的节点。这极大减少了因选择器错误导致的自动化失败。
3. 行动指令明确
结合Puppeteer的 page.click() 或 page.type(),Agent可以基于可访问性树中的节点信息,直接生成精确的定位和操作指令。整个流程是:理解结构 -> 决策 -> 生成代码 -> 执行,形成闭环。
实战案例:自动化信息抽取
假设你要做一个“比价Agent”,自动从三个电商网站抓取同一款手机的价格。
传统截图+OCR方案:
- Agent访问页面,截图。
- 调用多模态模型识别“价格”区域(可能识别错误)。
- 用OCR提取数字(可能识别错误)。
- 流程长,错误率高,成本高。
使用本MCP Server的方案:
- Agent调用MCP Server的工具,获取三个页面的可访问性树。
- LLM分析树结构,在每个页面中精准定位
role: "text", name: "价格"或类似语义的节点。 - 直接提取节点的
value或name中的价格数字。 - 一次调用,结构化输出,准确率接近100%。
另一个例子是自动化表单填写。Agent拿到表单的可访问性树后,能清晰地知道需要填写“姓名”、“邮箱”、“地址”等字段,并对应到具体的输入框。它甚至能识别出哪些字段是“必填”(通过states属性),从而生成更可靠的填写策略。
“视觉模式”:是备胎,也是王牌
这个Server提供了一个可选的“视觉模式”——即在提取可访问性树的同时,也生成页面截图。
在90%的场景下,你不需要它。 结构化数据已经足够。
但在10%的复杂场景下,它是救命稻草。 比如:
- 验证码识别:需要“看”图片内容。
- 复杂图表理解:需要“看”柱状图的趋势、饼图的比例。
- 非标准UI组件:某些高度定制化的交互组件,其可访问性信息可能不完整,需要视觉辅助判断。
这种“结构化为主,视觉为辅”的混合模式,是一个非常聪明的商业定位。它把核心功能(结构化翻译)做到极致轻量和高效,同时为高阶需求保留了扩展性。
作为开发范例的启示
如果你想开发自己的MCP Server,这个项目是一个绝佳的参考:
- 明确核心价值:它不追求大而全,而是解决“为LLM提供网页上下文”这一个具体痛点。
- 选择合适的技术:Puppeteer + CDP是获取浏览器内部数据的最直接路径。
- 做好数据预处理:原始数据往往不能直接用,过滤和格式化是提升体验的关键。
- 设计清晰的工具接口:对外暴露的工具(如
getAccessibilityTree,takeScreenshot)功能单一、语义明确。
下一步行动
- 亲自试试:在GitHub上找到这个项目(搜索
puppeteer-accessibility-mcp或类似关键词),按照README在本地跑起来。用它去“读”几个你常去的网站,看看输出的结构是什么样。 - 改造你的Agent:如果你正在开发一个需要网页交互的Agent,尝试用它替换掉原来的截图或HTML解析模块,对比一下Token消耗和任务成功率。
- 动手开发:以此为模板,思考你常用的其他数据源(比如某个API、某个数据库),能否也封装成一个为LLM优化的MCP Server。为LLM设计数据接口,是下一代工具开发的核心范式。
别再让LLM“猜”网页了。给它一份清晰的“地图”,它的能力会超乎你想象。