之前做 AI Agent 项目时,最头疼的一步并不是模型选型,而是“如何让 Agent 真正操作一个网站”。让模型读网页、猜表单、模拟点击,既脆弱又容易被页面改版拖垮;把接口硬编码给模型,又等于放弃了第三方站点的长尾能力。最近 OpenAI 在 Agent 生态上放出一个新方向:WebMCP。简单说,它让网站主动把工具列表暴露给 AI Agent,而不是让 Agent 像人类一样去“看网页猜按钮”。这种思路很值得单独写一篇完整分析。
本文适合正在做 AI Agent 开发、浏览器插件开发,或者关注 Chrome 侧边栏智能助手的人。读完你会理解 WebMCP 的核心定位,掌握 Codex CLI 与 Chrome 扩展侧边栏的调试方式,并能基于本地 Demo 完整模拟“Agent 发现工具 → 调用接口 → 返回结构化结果”的链路。文中代码都给了完整可运行示例,环境配置也可以直接复用。
1. 背景与核心概念:WebMCP 到底解决了什么问题
1.1 从 Agent 操作网站的三种老办法说起
在 WebMCP 出现之前,AI Agent 要调用一个网站的能力,大致有三种路线。
第一种是 Function Calling / Tools API。模型本身不直接执行代码,而是根据用户输入输出一个结构化参数,例如{"city": "北京"},然后由开发者自己的服务端去查天气、下单、发消息。这种方式适合“你已经拥有了接口”的场景,问题在于每个接口都要人工注册,Agent 无法发现未知站点的新能力。
第二种是 MCP(Model Context Protocol)。它把本地文件、数据库、外部 API 统一成一套资源与工具协议,Agent 通过 MCP Server 连接能力。MCP 解决的是“Agent 与本地服务/SDK 之间怎么对话”,但面对公网上的任意一个网站时,仍然需要网站方主动提供兼容 MCP 的服务端点。
第三种是浏览器自动化。让 Agent 读取页面 DOM、识别点击区域、模拟输入,甚至通过截图让多模态模型理解页面布局。这种方法最通用,但也是开销最高的:页面结构一变,规则就失效;验证码、登录墙、反爬机制都会阻碍 Agent;更重要的是,这种“伪装成用户操作”的方式,在权限和安全边界上非常模糊。
WebMCP 的思路是把上面三种方案的长处结合起来:网站像声明 RSS 一样声明“我能做什么工具”,Agent 像调用本地 MCP 工具一样调用远端网站的工具,浏览器插件负责发现、授权、请求与上下文回传。
1.2 核心概念:让网站把工具“主动交出来”
WebMCP 的全称可以理解为 Web Model Context Protocol,核心思路是在网站域名下放置一个标准化的工具清单文件。这个文件描述网站提供的每个工具的名称、用途、入参格式、请求方式、认证要求等。AI Agent 访问站点时,可以先请求这个清单,再根据用户指令选择合适工具并发起调用。
类比一下:RSS 让网站主动暴露内容更新,WebMCP 让网站主动暴露“能力”。以前 Agent 需要从网页文本里推断“这里可能有个天气查询功能”,现在网站直接告诉 Agent:“我有一个get_weather工具,入参是城市名,接口路径是/api/weather。”这种声明式设计,把“让 Agent 猜”变成了“让网站说清楚”。
从研究角度看,WebMCP 更关注两个核心问题:工具发现(Discovery)和授权边界(Authorization)。工具发现解决 Agent 如何知道一个网站有哪些能力;授权边界解决 Agent 在什么权限下可以调用、哪些敏感操作需要用户二次确认。
1.3 WebMCP 与 MCP、Function Calling 的关系
很多开发者容易混淆这三个概念,这里用一张表格说明:
| 方案 | 作用层级 | 解决什么问题 | 典型使用场景 |
|---|---|---|---|
| Function Calling | 模型层 | 让模型输出结构化工具参数 | 开发者自定义函数,模型按 schema 生成 JSON 参数 |
| MCP | 工具/资源层 | 统一 Agent 与本地或远程服务之间的工具通信 | 本地 IDE、文件系统、数据库工具接入 Agent |
| WebMCP | Web 站点层 | 让公网网站向 Agent 暴露工具清单 | 任意第三方网站被 Agent 发现并调用 |
可以理解为:Function Calling 是模型侧的“参数协议”,MCP 是工具侧的“通信协议”,WebMCP 是网站侧的“开放声明协议”。三者并不互斥,实际落地时可能叠加使用:WebMCP 负责发现,MCP 负责传输,Function Calling 负责让模型生成参数。
2. 环境准备:Chrome 侧边栏插件与 Codex CLI
2.1 安装 Chrome 与检查版本
要实现“Codex 进入 Chrome 侧边栏”,首先需要准备 Chrome 浏览器。推荐使用最新稳定版或 Beta 版,因为侧边栏相关 API 依赖较新的 Chromium 内核。
打开地址栏输入:
chrome://version确认浏览器版本和路径。再打开扩展管理页:
chrome://extensions/打开右上角“开发者模式”。开发调试阶段,我们不需要通过 Chrome 网上应用店安装,直接加载本地已解压的扩展即可。
需要注意,Chrome 对非 HTTPS 站点的访问限制越来越严格。本机 localhost / 127.0.0.1 属于可信开发环境,不会触发安全拦截;但如果 WebMCP 工具站点部署在公网,必须配置 HTTPS 证书,否则扩展可能会因为“网站未使用安全连接”而无法获取清单文件。
2.2 安装 Codex CLI
Codex 是 OpenAI 推出的 AI 编程与 Agent 执行工具。侧边栏插件本身只是一个浏览器 UI,真正执行任务、调用模型、调用 WebMCP 工具的引擎仍然需要本地 CLI 支持。
如果你的机器上有 Node.js 环境,可以通过 npm 安装。Codex 官方仓库地址是github.com/openai/codex,建议先查看 README 中的最新安装方式。常见命令如下:
npm install -g @openai/codex安装完成后,在终端验证:
codex --version如果提示codex: command not found,说明 npm 全局 bin 目录没有加入 PATH。可以执行:
npm config get prefix然后把结果中的bin目录加入系统环境变量。Windows 下也可以通过where codex查找安装位置。
2.3 配置 Codex 账号与 API Key
Codex 运行时需要认证。最简单的方式是在终端执行:
codex login按照提示完成 OpenAI 账号授权。如果你希望用 API Key 方式接入,可以设置环境变量:
export OPENAI_API_KEY="你的 API Key"Windows PowerShell 下使用:
$env:OPENAI_API_KEY="你的 API Key"这里需要强调的是,API Key 是敏感凭据,不要提交到 Git 仓库,也不要写死在浏览器扩展代码里。侧边栏插件与本地 CLI 的通信,应该走本地消息通道,而不是在前端页面保存 Key。
3. 核心原理拆解:从用户指令到 WebMCP 工具调用
3.1 WebMCP 清单文件的初步设计
虽然 WebMCP 协议还在快速演进,但从公开资料和演示来看,它的核心是一个 JSON 清单。本文以本地 Demo 为例,先给出一个最小可用的清单结构,方便理解协议思路。
{ "webmcp": "0.1", "name": "天气查询工具站", "tools": [ { "name": "get_weather", "description": "根据城市名称获取当前天气信息", "inputSchema": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称,例如北京" } }, "required": ["city"] }, "endpoint": "/api/weather", "method": "GET", "auth": "none" } ] }关键字段解释:
webmcp:协议版本号。这个字段会随着官方迭代变化。name:站点或工具集的名称,用于 Agent 展示。tools:工具列表。name:工具名称,Agent 调用时使用。description:自然语言描述,帮助模型判断何时应该调用该工具。inputSchema:入参 JSON Schema,约束模型生成参数。endpoint:工具的实际请求路径。method:HTTP 方法,常见为 GET 或 POST。auth:认证要求,例如none、apiKey、oauth。这是安全边界的重要标识。
这里需要特别说明:以上字段是本文基于演示需要整理的简化结构,WebMCP 正式协议可能包含更多细节。实际开发时请以官方最新规范为准。
3.2 Agent 浏览器扩展的关键模块
一个支持 WebMCP 的 Chrome 侧边栏扩展,通常拆成几个模块:
第一个是工具发现模块(Discovery Module)。它负责在 Agent 访问站点时,尝试请求/.well-known/webmcp.json或站点声明的其他路径,并解析清单内容。
第二个是参数解析模块(Schema Parser)。模型根据工具描述生成参数后,扩展需要校验参数是否符合inputSchema,避免生成缺失必填字段或错误类型。
第三个是请求调用模块(Invoker)。扩展根据工具的endpoint和method,代为发出 HTTP 请求。这一步需要考虑跨域、CORS、认证头等问题。
第四个是权限管理模块(Permission Manager)。对于敏感操作,例如下单、转账、修改数据,扩展必须弹窗让用户确认,不能静默执行。
第五个是上下文回传模块(Context Hook)。拿到工具返回结果后,扩展要把结构化结果注入对话上下文,让模型基于真实数据生成最终回复。
3.3 一次完整的调用链路
我们以用户输入“帮我查一下北京的天气”为例,拆解完整流程:
- 用户在侧边栏输入指令,点击发送。
- 侧边栏脚本把指令交给本地 Agent 引擎(Codex CLI)。
- Agent 规划阶段判断需要调用“天气查询工具”。
- Agent 请求当前站点域名下的 WebMCP 清单文件。
- 解析清单,找到
get_weather工具,读取参数 Schema。 - 模型根据用户意图生成参数
{"city": "北京"}。 - 扩展校验参数,弹出或确认权限(本例为只读工具,可不弹窗)。
- 扩展向
/api/weather?city=北京发起请求。 - 后端返回 JSON 结果。
- Agent 把结果整理为“北京当前 25 摄氏度,晴朗”,展示给用户。
这条链路最大的变化在于,第 4 步到第 8 步不再依赖“读取页面 DOM”,而是通过标准协议直接调用。网站的交互方式无论如何改版,只要 WebMCP 清单不变,Agent 就能稳定工作。
4. 实战:用 Chrome 侧边栏让 Codex 调用 WebMCP 工具
这一节我们在本地跑通完整 Demo。整体分为三步:第一步写一个带 WebMCP 清单的 Node 服务;第二步写一个 Chrome 侧边栏扩展;第三步在浏览器中加载扩展并模拟 Agent 调用。
4.1 创建 WebMCP 演示站点
先创建一个项目目录:
mkdir webmcp-demo cd webmcp-demo初始化 package.json:
npm init -y为了减少依赖,我们直接用 Node.js 内置的http模块写服务端。创建server.js:
// webmcp-demo/server.js const http = require('http'); const server = http.createServer((req, res) => { const url = new URL(req.url, `http://${req.headers.host}`); // 设置 CORS,方便浏览器扩展跨域访问 res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS'); if (url.pathname === '/.well-known/webmcp.json') { const manifest = { webmcp: '0.1', name: '天气查询工具站', tools: [ { name: 'get_weather', description: '根据城市名称获取当前天气信息', inputSchema: { type: 'object', properties: { city: { type: 'string', description: '城市名称,例如北京' } }, required: ['city'] }, endpoint: '/api/weather', method: 'GET', auth: 'none' } ] }; res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify(manifest, null, 2)); return; } if (url.pathname === '/api/weather') { const city = url.searchParams.get('city') || '未知城市'; const weather = { city, temperature: Math.floor(Math.random() * 10 + 15), condition: '晴', updatedAt: new Date().toISOString() }; res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify(weather, null, 2)); return; } const html = `<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>WebMCP 演示站点</title> </head> <body> <h1>WebMCP 演示站点</h1> <p>本页面通过 /.well-known/webmcp.json 暴露工具给 AI Agent。</p> </body> </html>`; res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(html); }); const PORT = 3000; server.listen(PORT, () => { console.log(`WebMCP demo server running at http://localhost:${PORT}`); });启动服务:
node server.js打开浏览器访问http://localhost:3000/.well-known/webmcp.json,如果能看到带tools字段的 JSON,说明服务端正常。
4.2 编写 Chrome 侧边栏扩展
在webmcp-demo同级目录创建codex-sidebar文件夹:
mkdir codex-sidebar cd codex-sidebar创建manifest.json:
{ "manifest_version": 3, "name": "Codex WebMCP Sidebar Demo", "version": "0.1.0", "permissions": ["sidePanel", "storage"], "host_permissions": ["http://localhost/*", "http://127.0.0.1/*"], "side_panel": { "default_path": "sidebar.html" }, "background": { "service_worker": "background.js" } }创建sidebar.html:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <style> body { font-family: system-ui, sans-serif; padding: 12px; } textarea { width: 100%; height: 80px; margin-bottom: 8px; box-sizing: border-box; } button { width: 100%; padding: 8px; background: #10a37f; color: #fff; border: none; border-radius: 6px; cursor: pointer; } pre { background: #f6f8fa; padding: 8px; border-radius: 6px; white-space: pre-wrap; word-break: break-all; } </style> </head> <body> <h3>Codex 侧边栏</h3> <textarea id="prompt" placeholder="请输入你的指令,例如:查询北京的天气"></textarea> <button id="send">发送给 Agent</button> <pre id="result">等待指令...</pre> <script src="sidebar.js"></script> </body> </html>创建sidebar.js:
// codex-sidebar/sidebar.js const promptInput = document.getElementById('prompt'); const sendBtn = document.getElementById('send'); const result = document.getElementById('result'); sendBtn.addEventListener('click', async () => { const prompt = promptInput.value.trim(); if (!prompt) return; result.textContent = 'Agent 正在处理...'; try { // 1. 发现工具:读取 WebMCP 清单 const manifest = await fetch('http://localhost:3000/.well-known/webmcp.json').then((res) => res.json()); // 2. 模拟 Agent 决策:从用户指令中提取城市 const tool = manifest.tools[0]; const city = prompt.includes('北京') ? '北京' : prompt.includes('上海') ? '上海' : '广州'; // 3. 调用工具端点 const url = `http://localhost:3000${tool.endpoint}?city=${encodeURIComponent(city)}`; const weather = await fetch(url).then((res) => res.json()); // 4. 展示结构化结果 result.textContent = JSON.stringify( { manifest: manifest.name, tool: tool.name, input: { city }, output: weather }, null, 2 ); } catch (error) { result.textContent = `调用失败:${error.message}`; } });创建background.js:
// codex-sidebar/background.js // 生产环境中,background 会把侧边栏消息转发给本地 Codex CLI, // 通过 Native Messaging 桥接执行完整 Agent 流程。 chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.type === 'AGENT_REQUEST') { sendResponse({ status: 'ok', message: '已收到指令,等待本地 Agent 处理。' }); } });这里补充说明:实际运行时,扩展不能直接在前端页面调用 Codex CLI。标准做法是使用 Chrome Native Messaging,在本地写一个消息宿主程序,由后台 Service Worker 通过chrome.runtime.connectNative与 CLI 通信。上面代码中的sidebar.js先用fetch直接访问本地服务,是为了让 Demo 不依赖复杂桥接,聚焦在 WebMCP 的调用链路上。
4.3 在 Chrome 中加载扩展
打开chrome://extensions/,开启“开发者模式”,点击“加载已解压的扩展程序”,选择codex-sidebar文件夹。
加载成功后,在 Chrome 右上角点击扩展图标,或从侧边栏面板入口打开侧边栏。输入“查询北京的天气”,点击“发送给 Agent”。
4.4 运行结果说明
如果一切正常,侧边栏pre区域会显示类似内容:
{ "manifest": "天气查询工具站", "tool": "get_weather", "input": { "city": "北京" }, "output": { "city": "北京", "temperature": 24, "condition": "晴", "updatedAt": "2026-08-01T12:00:00.000Z" } }这个效果虽然简单,但已经完整复现了 WebMCP 的核心链路:站点声明工具 → 扩展发现清单 → 模型/规则生成参数 → 调用接口 → 结构化结果回传。实际产品中,input和output之间的“参数生成”环节由 Codex 完成,而不是简单的字符串匹配。
5. 常见报错与排查思路
在本地调试 Codex 与 Chrome 侧边栏过程中,最容易踩到下面几个问题。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
运行 Codex 时提示unable to locate the codex cli binary | Codex 可执行文件不在 PATH 中,插件或 IDE 找不到 CLI | 用npm config get prefix找到全局 bin 目录,加入 PATH;或在插件设置里指定codex_cli_path |
ChatGPT/App 启动时报unable to locate the codex cli binary | 桌面端调用 CLI 时环境变量不完整 | 在桌面端启动前先配置 PATH,确认codex --version可执行;Windows 上注意重启终端 |
chatgpt failed to start相关错误 | CLI 版本与桌面端版本不匹配,或安装不完整 | 重新安装 Codex CLI,检查 npm 全局目录权限,必要时清理缓存后重装 |
cc switch local proxy failed while handling codex endpoint /responses | 本地转发失败,Endpoint 地址配置错误或本地服务未启动 | 检查本地服务是否监听对应端口,确认请求端点是否可访问,重启 CLI 与浏览器插件 |
| Chrome 阻止扩展下载 | 扩展未签名,或站点不是 HTTPS 安全连接 | 开发阶段使用开发者模式加载已解压扩展;公网部署必须配置 HTTPS |
| 访问 WebMCP 清单返回 404 | 清单路径不正确,或静态服务器未配置对应路由 | 确认路径是否为/.well-known/webmcp.json,检查服务端路由 |
| 扩展请求本地服务被 CORS 拦截 | 服务端未设置跨域响应头 | 在服务端添加Access-Control-Allow-Origin: *,并处理 OPTIONS 预检请求 |
如果遇到不确定的问题,可以按以下顺序排查:
- 先在终端单独运行
codex --version,确认 CLI 可用。 - 再访问清单地址,确认服务端返回合法 JSON。
- 用
curl模拟工具调用,确认工具端点本身正常。 - 最后回到扩展里看报错,区分是权限问题、网络问题还是参数问题。
这个排查顺序的好处是,把“本地 CLI”和“浏览器扩展”两个环境隔离开,问题出在哪一层就能快速定位。
6. 从实测中总结的工程建议
6.1 网站开发者:如何设计 WebMCP 工具清单
如果你的网站准备接入 WebMCP,第一原则是“工具粒度尽量小”。一个工具只做一件事,比如“查天气”“下单”“查订单状态”,不要设计一个execute_all之类的万能接口。工具描述要写清楚,因为模型依赖描述来决策。描述越模糊,Agent 越容易误用。
第二原则是“不要暴露内部字段”。WebMCP 清单是公开文件,任何 Agent 和开发者都能看到。如果你把内部数据库字段、管理后台路径写进 Schema,等于把攻击面拱手送人。建议对外提供一层独立的 API 服务,只暴露必要字段,服务端做参数校验、限流和白名单控制。
第三原则是“明确区分只读工具和写操作”。例如天气查询是只读工具,可以静默调用;发起支付、修改资料、删除数据这类工具,必须在协议层声明auth和高风险标记,浏览器端必须弹出用户确认界面。
6.2 Agent 开发者:权限与安全边界是第一位
Agent 框架接入 WebMCP 时,不要无条件信任站点返回的清单。恶意站点可以伪造清单,诱导 Agent 调用来路不明的接口。建议在扩展层做域名白名单、工具风险分级、单次授权时长限制。
在日志方面,要记录完整的调用链:用户指令、Agent 决策、工具选择、入参、返回值、耗时。这样一旦 Agent 误调用了某个工具,可以回放定位。对于包含个人信息或敏感数据的工具响应,日志要脱敏,避免把完整数据写进本地文件。
6.3 前端插件开发:侧边栏应当与网页隔离
Chrome 侧边栏页面和普通插件弹窗不同,它常驻在浏览器右侧,和网页内容同时展示。在实现上,建议使用独立的sidebar.html,不要直接操作当前页面的 DOM。网页的 CSS 可能影响插件样式,务必在侧边栏页面内写完整的样式隔离。
与 Codex CLI 的通信,尽量走 Native Messaging。不要把 API Key 放在扩展的storage中,也不要通过公网中转。本地消息桥虽然部署麻烦一点,但安全性远高于在浏览器里保存凭据。
7. 总结与下一步学习路线
WebMCP 最值得关注的并不是“又一个新协议”,而是它把 AI Agent 和网站的关系从“Agent 模拟用户操作”变成“网站主动提供工具接口”。这个转变如果能规模化落地,浏览器插件的存在形式会发生变化:侧边栏不再只是一个聊天框,而是一个能理解站点能力、调用站点工具、处理真实业务的 Agent 入口。
下一步建议按这个顺序深入学习:
- 先把本文的 Node 服务和 Chrome 扩展跑通,理解工具发现与调用链路。
- 阅读 Codex CLI 官方文档,尝试在终端里让 Codex 完成一个本地任务。
- 研究 Native Messaging 机制,把侧边栏与本地 CLI 真正连起来。
- 选择一个自己维护的站点,设计一份完整的 WebMCP 清单,包括认证与权限字段。
- 关注 WebMCP 协议版本更新,因为这是一个快速迭代的方向,今天简化过的字段明天可能就会变成正式规范。
在实际项目中,优先关注权限模型和数据安全。工具清单公开是好事,但公开到什么程度、谁可以调用、调用后能拿到什么数据,这些问题比协议本身更影响生产环境的稳定性。如果你的项目正在做 AI Agent 接入第三方网站,可以先用本文的 Demo 验证一遍调用链路是否顺畅,再决定是否把 WebMCP 纳入正式技术选型。