Skip to content

Purview 是什么

Purview 实现了 MCP GUI Bridge Protocol v0.1.0。它位于你真实的 GUI 与 MCP 客户端之间,对外提供应用的一份投影:一组窗口,每个窗口携带若干语义化内容块(字段、表格、列表、通知、媒体……)以及动作。

你无需自己拼装任何协议消息。你只负责描述窗口并让它保持最新,剩下的交给库。

为什么叫 Purview

英文里的 purview 指一个人被允许看到、被允许决定的范围——常见搭配是 within the purview of(在……的职权范围之内)。这恰好就是投影的含义:投影就是 agent 对你的应用所拥有的 purview。你放进投影的内容,agent 才读得到;你暴露出来的动作,agent 才调用得到。其余的一切并不是被一道权限检查挡在门外——它根本不会出现在协议消息里。

这个词里还藏着 view,这是故事的另一半:agent 拿到的始终是你 GUI 的一份视图,而不是 GUI 本身。它无法点击你的按钮,也无法越过投影去触碰你的控件;它只能通过你定义的动作,请求某件事发生。

三个核心理念

核心不绑定 GUI 框架。 purview crate 不链接任何 GUI 工具包。它只通过你在启动时注册的一个闭包抵达主线程。

语义化,而非像素。 Agent 读到的是结构化内容块——带标签的字段、有类型的行——而不是一张需要它自行辨认的截图。

协议由库负责。 动态 tools/list、模态链、乐观并发、脱敏、通知:全部由你维护的那份投影推导得出。

该用哪个 crate?

Crate适用场景
purview总是需要。它是核心:投影、协议、服务端。
purview-gpui你的 UI 基于 gpui。它省掉了线程调度的样板代码——参见 使用 purview-gpui

心智模型

一共两条数据流,把它们分清楚是最重要的一个习惯:

读侧(GUI → 库)。 你的 UI 在变更事件中,通过此前保留的类型化句柄把新值写入投影。这是内容块唯一发生变化的地方。

写侧(Agent → GUI)。 每个动作都会成为一个 MCP 工具。它的处理器触发真实的业务逻辑或 GUI 操作;它直接修改投影——变更会经由读侧回流。

为什么这很重要

如果处理器直接写投影,那么 Agent 触发的变更与人触发的变更就走了两条不同的路径,迟早会出现分歧。把所有变更收拢到同一个方法里——本文档的例子都统一用一个 sync()bump()——投影就不可能失真。

你需要持有的三样东西

句柄来自用途
AppHandle<Cx>build()打开窗口;读取快照
Window<Cx>app.open(title)摘要、内容块、动作、模态、关闭
内容块句柄win.blocks().fields(..)之后更新对应的内容块

它们全都可以廉价克隆,满足 Send + Sync,并且只持有共享核心的弱引用——所以你可以把它们存进 GUI 组件,并从任意线程调用。一旦核心被释放,它们的操作会安全地退化为空操作。