MCP 起初是让模型与工具对话的协议。模型问服务器有什么,调用工具,拿到结果。人在这段对话之外,需要画面时就回到文字。
工具变多之后,文字不够了。要给出表格,要打开地图,要按下按钮。需要窗了。
分歧就在这里。窗不是一种。
窗 ① — 模型给人看的窗
2025 年 11 月,MCP-UI 社区和 OpenAI 的 Apps SDK 在各自解决同一个需求。两者合并成 MCP Apps(SEP-1865),作为 MCP 第一个正式扩展达到 Final。
结构是这样的。
- 服务器用
ui://方案预先声明 UI 资源 - 工具通过元数据引用该资源
- 工具被调用时,宿主在沙箱 iframe 中渲染 HTML
- iframe 与宿主双向通信
- UI 调用工具时要取得用户同意
这是设计良好的规范。预先声明让宿主可以先取、缓存并做安全审查;iframe 沙箱把不可信服务器的 UI 隔离开。只处理 HTML 的决定也很明确 — 到处都能跑、安全模型简单、可以截图。
这扇窗归模型所有。 对话中工具被调用,结果显示为画面。对话的表达力变宽了。

窗 ② — 人直接操作机器的窗
可是有这样的场景。
船的驾驶室。发动机状态、燃油、压载、发电机。轮机长在控制台上直接操作。船长用平板只看仪表。甲板上的船员用手机只收警报。同一台设备,不同的画面,不同的权限。
这里没有模型。有当然更好 — 能先说一句「3 号发电机温度已经上升 15 分钟」当然更好。但没有它船也照走。 轮机长看着仪表去握阀门。
特种车的控制盘、农机的作业机操作、工厂设备的运行盘,都一样。这是人直接操作机器的窗。 不是工具调用的产物,而是操作面本身。
这扇窗本来不是 MCP 瞄准的位置。但 MCP 已经握着做这件事的材料 — 设备把自己的功能作为工具暴露、把状态作为资源发布、把变化通知出去。缺的是画面。
为什么窗①做不出窗②
不是高下问题,是设计前提问题。四条都写在 MCP Apps 的规范里。
第一,HTML 与 iframe 是要求。 渲染对象是 HTML,沙箱化不是可选而是必需。几十 KB 内存的单片机没有 HTML 引擎,也没有 iframe。在设备必须在自己 LCD 上作画的场合,这条要求是过不去的墙。
第二,工具被调用,UI 才出现。 回路是 模型 → 工具 → UI → 用户。把模型拿掉,窗就不会打开。 而驾驶室的控制台,只要船上通电就必须亮着。
第三,没有「通道」这根轴。 「同一台设备在驾驶室给控制权,在手机上只给查看」— 没有地方表达这个区分,因为开窗的宿主只有一个。
第四,威胁模型方向相反。 MCP Apps 要防的是「不可信的服务器把恶意 UI 送进我的聊天客户端」。设备控制要防的是「谁可以操作这台机器」。前者保护用户,后者保护机器与人的安全。
两扇窗并不竞争
MCP Apps 是模型给人看的窗,设备控制面是人直接操作机器的窗。前者拿掉模型就消失,后者没有模型也照转。
而且两扇窗可以同处一屏。模型一边说出异常征兆一边给出趋势图(窗①),旁边轮机长直接操作阀门(窗②)。
设计者说的也是这幅画面 — 他把模型对话的窗口做成了人也能一起对话的窗,而且可以一起看着做。
到这里是第二条轴
第一条轴在生意层问生意归谁,第二条轴在协议层问窗归谁。层不同,两个答案就不互相削减。
从下一篇起是画面。窗②到底怎么做出来 — 设备把自己的画面递过来是什么意思,用桌上的两块板来确认。
makemind.dev 「探索」— 关于 MCP Apps 的描述全部核对自它自己的规范。