午夜咖啡午夜咖啡

jolestar 的文章与笔记。

Post

从和 AI 一起画架构图开始:WebMCP 与 webmcp-bridge

2026-03-15 10:22:38Post

真正有意思的不只是 AI 会不会画图,而是浏览器里的应用能力,能不能自然地接到本地 Agent 的工作流里。

我一直想找一个让 AI 帮我画架构图的工具。

直接让模型生成一张图当然可以,但这种方式有个很明显的问题:图一旦生成出来,后续调整就不顺。你想改一下布局、补一条边、挪几个节点,往往又得重新描述一遍,最后很容易退化成“再生成一次”。

另一种思路是用网页里的画图工具,再加一点 AI 辅助。但这类方式也有一个限制:网页里的 AI 通常拿不到我本地正在看的代码、文档和上下文。它能帮你画,但很难真正进入我的工作流。

所以我更想要的,其实是第三种方式:画布留在浏览器里,但调用它的 AI 是我自己的 Codex 或 Claude Code。这样一来,AI 一边可以利用我本地已有的上下文,一边又可以直接在可编辑的画布里帮我改图,而不是只吐一张静态结果。

顺着这个想法,我先做了一个 demo:

https://board.holon.run

它是一个基于 Excalidraw 的 board。人可以直接在页面里拖动、编辑、选中;AI 也可以在同一个画布里读图、加节点、连边、调整布局。关键不在于“AI 也能画图”,而在于人和 AI 可以作用在同一个浏览器会话里。

这时候,问题就从“怎么画图”变成了“本地 agent 怎么碰到浏览器页面里的能力”。

这也是我后来关注 WebMCP,并做了 webmcp-bridge 的起点。

WebMCP 是什么

如果说 MCP 解决的是“如何给模型暴露工具”,那 WebMCP 可以理解成这件事在浏览器侧的延伸:网页自己暴露工具,AI 通过浏览器里的接口去调用。

在这个项目里,最核心的接口就是 navigator.modelContext

如果一个网站支持原生 WebMCP,那么它就可以直接在页面里通过这个接口暴露能力。AI 不需要分析页面布局、模拟用户操作,而是直接调用页面暴露出来的能力。

不过 WebMCP 官方现在的思路,更接近“让浏览器里的 agent 去调用网页能力”,而不是让一个纯本地的 CLI agent 直接连到网页。网页通过 navigator.modelContext 在浏览器里暴露工具,浏览器内建的 AI、浏览器扩展,或者由浏览器承载的 agent 去发现和调用这些工具。

从这个角度看,WebMCP 解决的是“网页如何在浏览器里暴露能力”,但它没有天然解决“我本地的 Codex / Claude Code 怎么用上这些能力”。这也正是 webmcp-bridge 想补上的那一层。

webmcp-bridge 做了什么

问题在于,大多数本地 agent 更习惯调用本地 MCP server,而 WebMCP 的能力却在浏览器页面里。中间天然有一条断层。

webmcp-bridge 做的事情很简单:把这条调用路径桥接起来。

它的主路径是:

local-mcp -> playwright -> browser navigator.modelContext

也就是:

  1. 本地 agent 调用一个普通的 stdio MCP server,也就是 local-mcp
  2. local-mcp 通过 Playwright 驱动浏览器页面
  3. 如果页面支持原生 WebMCP,就直接调用 navigator.modelContext
  4. 如果页面还没支持 WebMCP,就走 shim / adapter fallback

这里我比较看重的一点是:webmcp-bridge 不是替网站重写一套 API,而是尽量让能力留在浏览器里,只把调用路径桥接回来。

这也是为什么整个项目会坚持一个原则:

  • native-first
  • shim fallback

网站已经支持 WebMCP,就直接走原生路径;还没支持,再补一层 adapter。这样未来 WebMCP 真正铺开之后,bridge 不会变成负担;而在今天,它又能让很多还没支持 WebMCP 的网站先接起来。

怎么通过 UXC 来用

对我来说,UXC 在这里扮演的是统一调用层。它把这条浏览器桥接路径固化成稳定命令,这样本地 agent 不需要记住一长串启动参数,也不需要把一堆 MCP 配置塞进上下文。

比如针对 board 这个 demo,可以先创建两个 link。实际使用时,这一步也可以交给 skill 自动完成:

uxc link board-webmcp-cli \
  "npx -y @webmcp-bridge/local-mcp --url https://board.holon.run --headless --user-data-dir ~/.uxc/webmcp-profile/board" \
  --daemon-exclusive ~/.uxc/webmcp-profile/board

uxc link board-webmcp-ui \
  "npx -y @webmcp-bridge/local-mcp --url https://board.holon.run --no-headless --user-data-dir ~/.uxc/webmcp-profile/board" \
  --daemon-exclusive ~/.uxc/webmcp-profile/board

这样,board-webmcp-cli 负责 headless 调用,board-webmcp-ui 则把同一个会话打开给人看。

后面的协作路径就很直接了:

board-webmcp-ui bridge.open

# AI
board-webmcp-ui nodes.upsert '{"nodes":[{"label":"Gateway","kind":"service","x":200,"y":120}]}'
board-webmcp-ui edges.upsert '{"edges":[{"sourceNodeId":"gateway","targetNodeId":"orders","protocol":"grpc"}]}'
board-webmcp-ui layout.apply mode=grid

也就是说,人打开浏览器看着画布,AI 在同一个会话里增删节点、加边、调布局。这个模式和“AI 生成一张图然后扔给人看”不是一回事,它更接近协作编辑。

我想验证的是什么

我想验证的,不只是 AI 能不能操作网页。

我更想验证的是:WebMCP 能不能成为浏览器应用和本地 AI 之间一层自然的接口。也就是:

  • 网站在浏览器里提供能力
  • 本地 agent 通过 MCP 去调用
  • native 优先,fallback 可用
  • 人和 AI 在同一个网页会话里协作

如果这条路成立,那很多现在还要靠脚本模拟、接口逆向、状态搬运的事情,都会简单很多。

仓库和 demo: