十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

在 MCP Apps 中集成 A2UI:构建基于 Python MCP Server 的交互式 UI 应用服务

在 MCP Apps 中集成 A2UI:构建基于 Python MCP Server 的交互式 UI 应用服务 在 MCP Apps 中集成 A2UI构建基于 Python MCP Server 的交互式 UI 应用服务【免费下载链接】a2ui项目地址: https://gitcode.com/GitHub_Trending/a2/a2ui导读本文基于 a2ui 仓库中的samples/community/mcp/a2ui-in-mcpapps/server示例系统讲解如何用 Python 编写一个 Model Context ProtocolMCP服务器将独立打包的 Web 应用作为 MCP App 资源对外提供并通过 MCP 工具tools把原始的A2UI JSON 载荷直接翻译为丰富的交互式 UI 渲染。读完本文你将掌握 MCP Server 中resources与tools的声明方式、_meta.ui.resourceUri的 UI 模板关联机制、SSE/Stdio 双传输通道的启动方式以及 A2UI 载荷dataModelUpdate/surfaceUpdate/beginRendering如何驱动界面增量更新。一、示例概览MCP 生态中的 A2UI 承载方式本示例位于仓库的 samples/community/mcp/a2ui-in-mcpapps整体分为三个部分server/Python uv构建的 MCP Server对外提供 micro-app 资源与交互工具是本文的主角client/Angular 编写的宿主容器应用通过安全的双 iframe 代理模式加载并隔离运行来自 MCP 的微应用server/apps/被托管的微应用源码Basic 计数器应用与 Editor 生成式文档编辑器构建为单文件 HTML 后交由 MCP Server 对外提供。其中server 端目录的核心文件与职责如下见 server/README.md文件/目录职责server.pyMCP Server 核心实现定义 tools、resources 与传输方式SSE / Stdiosimple_counter_a2ui.json示例 A2UI 载荷数据文件供fetch_counter_a2ui工具返回apps/被托管应用hosted application的源码与构建产物目录apps/public/app.htmlServer 实际对外服务的自包含单文件应用需先构建生成关键约束该 Server 专门期望服务位于apps/public/app.html的打包产物该文件缺失或源码变更后必须先重新构建详见下文托管应用构建一节。二、暴露的接口Resources 与 ToolsMCP Server 通过resources/read提供 MCP App 的 HTML 模板通过tools/call返回 A2UI 载荷来驱动界面渲染。2.1 Resources资源ui://basic/app对外提供自包含的apps/public/app.html应用MIME 类型为text/html;profilemcp-app。在 server.py 中list_resources除 basic 外还声明了第二个资源ui://editor/appEditor 应用并且read_resource会按 URI 映射到apps/public/下对应的app.html/editor.html文件。这里有一个关键实现细节resources/read的返回内容必须携带text/html;profilemcp-appMIME 类型而不仅仅是resources/list声明时带上——这是 MCP Apps 规范对资源读取的强制要求也是本示例特意在代码注释中强调的点。2.2 Tools工具基础计数器相关工具对应simple_counter_a2ui.jsonget_basic_app返回ui://basic/app资源的引用。该工具通过_meta.ui.resourceUri预声明 UI 模板宿主通过resources/read获取模板而不会把模板作为内嵌资源混进工具结果中见 server.pyfetch_counter_a2ui读取simple_counter_a2ui.json返回初始计数器 A2UI 载荷用于测试渲染increase_counter对内存计数器自增并返回标准的dataModelUpdate实现 UI 组件更新。生成式编辑器相关工具同一 server 文件中的扩展工具get_editor_app打开 Editor A2UI 应用视图通过_meta.ui.resourceUri关联ui://editor/appsmart_editor_get_controls根据用户选中的文本让 Gemini 生成 A2UI 调参控件slider / checkbox / selectsmart_editor_apply把用户在控件上调整后的参数提交给 Gemini 重写文本。每个工具都通过_meta.ui.visibility声明可见性如[model]仅模型可见、[app]允许应用调用。需要说明的是这些 Editor 扩展工具属于仓库中同一 server 代码的一部分是理解服务端如何为 MCP App 提供完整交互闭环的重要补充但计数器工具才是本文主体 README 所聚焦的基础演示。三、快速开始运行 MCP Server3.1 前置条件Python 3.10uv推荐的 Python 包管理工具可依据server/.python-version自动管理 Python 版本。3.2 方式 ASSE 传输默认在server/目录下启动默认监听127.0.0.1:8000等待 SSE 连接cd samples/community/mcp/a2ui-in-mcpapps/server uv run python server.py --transport sse --port 8000由于程序默认参数就是sse与端口8000也可以直接简写为uv run python server.py首次运行前建议先执行uv sync按 pyproject.toml 安装依赖click、mcp[cli]、sse-starlette、starlette、uvicorn、google-genai、python-dotenv等。3.3 方式 BStdio 传输使用标准输入输出与宿主进程通信适合作为子进程被 Agent 宿主拉起uv run python server.py --transport stdio传输方式的切换由 server.py 中的 click 参数控制click.command() click.option(--port, default8000, helpPort to listen on for SSE) click.option( --transport, typeclick.Choice([stdio, sse]), defaultsse, helpTransport type, )3.4 两种传输的底层实现差异SSE基于 Starlette Uvicorn 搭建 HTTP 服务Route(/sse)处理事件流连接Mount(/messages/)接收客户端 POST 消息同时注册了CORSMiddleware源码中带有明确警告生产环境必须将allow_origins[*]收紧为宿主客户端的具体来源例如http://localhost:4200Stdio通过mcp.server.stdio.stdio_server在标准输入输出上建立双向消息流并用anyio.run驱动事件循环。四、深入源码工具调用如何返回 A2UI 载荷handle_call_tool是界面驱动的核心其返回的CallToolResult中内嵌了 MIME 类型为application/a2uijson源码常量A2UI_MIME_TYPE的TextResourceContents见 server.pyget_basic_app/fetch_counter_a2ui把simple_counter_a2ui.json的内容序列化后以a2ui://ping-result为 URI 的内嵌资源返回increase_counter修改全局计数器后构造一个dataModelUpdate消息通过surfaceId: ping-result、contents中的{key: counter, valueNumber: COUNTER}精准更新数据模型中指定 key 的值前端据此重新渲染score-value文本。这种工具结果携带 A2UI JSON的方式让 Agent 宿主可以直接把载荷交给 A2UI 渲染层解析实现一次工具调用即完成一次界面更新。4.1 初始 A2UI 载荷剖析simple_counter_a2ui.json见 simple_counter_a2ui.json是 A2UI v0.8 规范的典型三段式消息序列dataModelUpdate声明surfaceId、path: /与数据内容如counter 0surfaceUpdate以组件清单描述 UI 树——Card包住Column内部依次是TextPong from MCP Server (v0.8)!、Row含计数器卡片与按钮。其中按钮通过action: {name: increase_counter, context: []}把用户点击映射回 MCP 工具调用而计数文本则通过text: {path: /counter}绑定数据模型beginRendering指定root: root作为渲染入口通知渲染器开始绘制该 surface。这一结构清楚展示了 A2UI 的数据模型 组件树 渲染指令分离设计以及action与数据绑定如何支撑起完整的交互闭环。五、托管应用的构建要求Server 对外服务的是apps/public/app.html这个自包含单文件产物。若该文件缺失或你修改了apps/src/下的托管应用源码都必须重新构建详见 apps/README.md。5.1 构建工作流在server/apps/src/目录下执行cd server/apps/src yarn install yarn build:allbuild:all会先执行 Angular 编译再触发node inline.js把产物内联为单文件public/app.html。5.2 为什么要单文件内联由于 MCP App 的安全隔离要求通常依赖沙箱 iframe例如srcdoc场景应用必须是一个不依赖外部请求的独立 HTML 文件。inline.js脚本的工作流程为收集 Angular 原始构建产物dist/raw下的index.html及 JS/CSS把所有 JavaScript 与 CSS 动态内联进index.html输出自包含的app.html到public/目录。以 Editor 应用的 inline.js 为例实现中还有两个值得注意的细节esbuild 强制打包Angular 17 默认启用 ES Module 代码分割main.js会依赖外部相对路径 chunk而在沙箱srcdociframe 中这些相对请求会被浏览器拦截缺乏可访问的 base origin因此脚本调用npx esbuild --bundle --formatesm将所有 split chunks 合并为单一文件后再内嵌清理 modulepreloadAngular 自动注入的link relmodulepreload在强制打包后会产生无意义的 404/CORS 网络错误脚本会将其全部剔除同时剥离 sourceMappingURL 以减小体积。5.3 构建产物与 Git 忽略dist/原始构建输出与public/最终打包产物均被 git 忽略全新 clone 的仓库默认没有这些产物Server 即使没有它们也能启动但对应 surface 无法加载。因此在端到端运行示例前至少需要构建一个应用。仓库根目录的 样例总览 提供了 Editor 与 Basic 两种应用的构建命令以及先yarn install链接工作区包的提醒。六、端到端运行与完整通信流程6.1 启动宿主客户端除 Server 外还需要构建宿主容器Angular Client的沙箱桥接资源并在 4200 端口启动cd samples/community/mcp/a2ui-in-mcpapps/client yarn install yarn build:sandbox # 生成 client/public/sandbox_iframe/sandbox.{js,html} yarn start # 打开 http://localhost:4200 查看运行中的宿主6.2 消息流转时序样例总览文档用 sequence diagram 描述了完整闭环简化版宿主从托管服务器加载向 MCP Server 发tools/list得到带_meta.ui.resourceUri指向ui://模板的工具定义宿主调用应用入口工具tools/call随后通过resources/read拉取声明的 HTML 模板宿主把模板 HTML 交给沙箱代理代理在隔离 iframe 中加载 MCP AppApp 内 CTA 触发后通过 代理 → 宿主 → Server 的链路转发工具调用Server 返回 A2UI JSON 载荷经宿主与代理中继后交由 App 内的 A2UI Surface 渲染组件用户在 A2UI 组件上点击时action被映射为tools/call请求再走同一链路回传dataModelUpdate最终完成增量渲染更新。宿主侧的 client/src/app/app.ts 中可见其实现要点监听window message事件并校验event.origin与event.source安全边界按每个工具声明的_meta.ui.visibility构建allowedTools集合并通过ui/notifications/sandbox-proxy-ready、ui/notifications/sandbox-resource-ready等约定消息与沙箱代理握手。七、扩展生成式文档编辑器中的 A2UI 动态控件除基础计数器外同一 Server 还演示了LLM 动态生成 A2UI 控件的高级用法实现于 smart_editor_agent.pygenerate_controls(text, full_text)把选中文本交给 Gemini默认模型gemini-2.5-flash可通过GENAI_MODEL环境变量覆盖通过response_schema约束输出 JSON得到 23 个调参控件随后把控件映射为 A2UI 组件——Slider0–100 数值、CheckBox布尔值、MultipleChoice下拉选项连同dataModelUpdate、surfaceUpdate、beginRendering三段消息返回给前端apply_revision(text, user_parameters)解析control_config_json中的控件定义把用户当前值格式化为自然语言指令如- Verbose vs. Concise: 0.30 (0 meaning low...)再要求 Gemini 输出text_before / original_text / revised_text / text_after四段式修订结果实现基于用户调参的文本重写。该扩展说明MCP Server 返回的 A2UI 载荷不必是静态 JSON——服务端可以借助 LLM 按上下文实时生成界面结构这正是 A2UI 面向 Agent 生态的灵活之处。八、总结与排查建议启动失败确认 Python ≥ 3.10且已uv syncSSE 模式下可开启日志观察连接建立源码中logging.basicConfig(levellogging.INFO)就是为此准备的surface 加载空白检查apps/public/app.html是否已构建Server 在read_resource找不到文件时会抛出ValueError: Resource file not found...跨域问题本地调试允许 CORS*但生产环境务必按源码警告收紧allow_origins换用 UI 模板新增应用时需同时修改list_resources、read_resource中的 URI 映射以及对应工具声明的_meta.ui.resourceUri。本示例的价值在于给出了一个可运行的最小参考实现从资源声明、工具返回 A2UI 载荷、单文件应用构建到宿主沙箱隔离与增量渲染完整串联了 MCP Apps 与 A2UI 的集成路径。相关可继续研读的仓库文件包括server.py、simple_counter_a2ui.json、apps/README.md 与 样例总览。【免费下载链接】a2ui项目地址: https://gitcode.com/GitHub_Trending/a2/a2ui创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表