新闻详情

新闻详情

首页 / 资讯中心 / 详情

基于 FastMCP 构建带交互界面的 QR Code MCP App:工具、`ui://` 资源与 CSP 配置实战

发布时间:2026/9/12 1:46:41来源:尧图网络
基于 FastMCP 构建带交互界面的 QR Code MCP App:工具、`ui://` 资源与 CSP 配置实战
基于 FastMCP 构建带交互界面的 QR Code MCP App工具、ui://资源与 CSP 配置实战【免费下载链接】fastmcp The fast, Pythonic way to build MCP servers and clients.项目地址: https://gitcode.com/GitHub_Trending/fa/fastmcp导读本文以仓库中的 examples/apps/qr_server 为完整示例讲解如何在 FastMCP 中构建一个MCP App带交互式 UI 的 MCP 服务器通过AppConfig把一个工具链接到ui://协议的资源由 HTML 资源借助modelcontextprotocol/ext-appsJS SDK 在沙箱 iframe 中渲染工具结果并通过ResourceCSP声明 CDN 域名以配合宿主设置 Content-Security-Policy。读完本文你将掌握mcp.tool/mcp.resource的app元数据、ImageContent二进制返回、stdio 与 HTTP 双模式运行以及使用fastmcp install将应用安装进 MCP 客户端的完整流程。示例概览QR Code MCP App 是什么qr_server是一个移植自 ext-apps 社区示例的最小可运行 MCP App 服务器它只做两件事注册一个generate_qr工具把任意文本/URL 编码为 base64 PNG 二维码图片注册一个ui://qr-server/view.html资源返回一段内嵌 HTML页面通过 MCP Apps JS SDK 接收工具结果并在界面中展示二维码。它重点演示了 FastMCP 对 MCP Apps 扩展io.modelcontextprotocol/ui的四个核心能力见 README.md通过AppConfig将工具链接到ui://资源通过 CDN 加载modelcontextprotocol/ext-appsJS SDK服务内嵌 HTML通过ResourceCSP声明资源允许的 CSP 域名工具返回ImageContentbase64 PNG二进制内容。从源码结构看见 qr_server.py整个应用只有约 170 行是理解 FastMCP Apps 机制的最小闭环样本。环境准备与依赖清单依赖声明pyproject.tomlqr_server项目的依赖声明在 pyproject.toml[project] name fastmcp-app-examples version 0.1.0 description MCP App examples for FastMCP requires-python 3.10 dependencies [ fastmcp, qrcode[pil]8.0, ] [build-system] requires [hatchling] build-backend hatchling.build注意两点qrcode[pil]8.0二维码生成依赖qrcode库[pil]extra 会同时引入pillow用于渲染 PNG 图像requires-python 3.10需要 Python 3.10 及以上版本。fastmcp.json面向客户端安装的声明式配置仓库还提供了 fastmcp.json这是 FastMCP 的服务器配置文件供fastmcp install等 CLI 读取{ $schema: https://gofastmcp.com/public/schemas/fastmcp.json/v1.json, source: { path: qr_server.py }, environment: { dependencies: [ fastmcp, qrcode[pil]8.0, pillow ] } }它声明了服务器入口qr_server.py以及运行所需依赖这样 MCP 客户端如 Claude Desktop在安装时可以自动解析入口并准备环境。初始化项目cd examples/apps/qr_server uv syncuv sync会根据pyproject.toml创建虚拟环境并安装fastmcp、qrcode[pil]等全部依赖。运行方式HTTP 模式与 stdio 模式qr_server.py在__main__中直接调用mcp.run()并支持两种传输模式见 qr_server.pyif __name__ __main__: mcp.run()方式一HTTP 模式默认端口 3001uv run python qr_server.py # HTTP mode (port 3001)在 HTTP 模式下FastMCP(QR Code Server)默认暴露一个流式 HTTP 端点端口 3001浏览器或 MCP 客户端可以通过 HTTP 传输访问该服务器这也是 MCP Apps 交互 UI 最自然的运行方式——宿主可以在 iframe 中加载ui://资源并调用工具。方式二stdio 模式面向 MCP 客户端uv run python qr_server.py --stdio # stdio mode for MCP clients--stdio切换为进程内标准输入/输出通信适合 Claude Desktop、Cursor 等通过子进程启动服务器的 MCP 客户端。方式三安装进 MCP 客户端fastmcp install stdio fastmcp.json该命令读取fastmcp.json把qr_server.py作为 stdio 服务器注册到 MCP 客户端配置中之后客户端即可直接发现generate_qr工具与ui://qr-server/view.html资源。核心实现逐行拆解1. 常量与入口from fastmcp import FastMCP from fastmcp.apps import AppConfig, ResourceCSP from fastmcp.tools import ToolResult VIEW_URI: str ui://qr-server/view.html mcp: FastMCP FastMCP(QR Code Server)VIEW_URI使用ui://scheme这是 MCP Apps 扩展约定io.modelcontextprotocol/ui见 apps/config.py 中的UI_EXTENSION_ID下标识 UI 资源的 URI 格式AppConfig、ResourceCSP从fastmcp.apps导入二者都是 Pydantic 模型负责承载工具/资源的 UI 元数据。2. 工具generate_qr与AppConfig(resource_uri...)mcp.tool(appAppConfig(resource_uriVIEW_URI)) def generate_qr( text: str https://gofastmcp.com, box_size: int 10, border: int 4, error_correction: str M, fill_color: str black, back_color: str white, ) - ToolResult: Generate a QR code from text.appAppConfig(resource_uriVIEW_URI)是关键的一行它告诉宿主——当用户需要以应用形态使用这个工具时应渲染ui://qr-server/view.html这个资源。从 apps/config.py 可以看到AppConfig的完整字段字段别名wire 格式作用resource_uriresourceUri工具关联的 UI 资源 URI仅工具使用通常为ui://visibility—工具可见范围app、model或两者csp—应用 iframe 的 Content-Security-Policypermissions—iframe 沙箱权限摄像头、麦克风等domain—iframe 的域名prefers_borderprefersBorderUI 是否偏好显示可见边框所有字段序列化时使用exclude_none别名遵循 MCP Apps wire 格式camelCase只会把显式设置的值放到线上。参数校验与错误处理工具内部对参数做了完整校验qr_server.pyerror_levels { L: qrcode.constants.ERROR_CORRECT_L, M: qrcode.constants.ERROR_CORRECT_M, Q: qrcode.constants.ERROR_CORRECT_Q, H: qrcode.constants.ERROR_CORRECT_H, } if box_size 0: raise ValueError(box_size must be 0) if border 0: raise ValueError(border must be 0) error_key error_correction.upper() if error_key not in error_levels: raise ValueError(ferror_correction must be one of: {, .join(error_levels)})参数含义与 docstring 一致text要编码的文本或 URL默认https://gofastmcp.combox_size每个模块box的像素尺寸默认 10必须大于 0border边框模块数默认 4必须不小于 0error_correction容错级别L(7%)、M(15%)、Q(25%)、H(30%)大小写不敏感fill_color/back_color前景/背景色支持十六进制#FF0000或颜色名red。生成二维码并以ImageContent返回qr qrcode.QRCode( version1, error_correctionerror_levels[error_key], box_sizebox_size, borderborder, ) qr.add_data(text) qr.make(fitTrue) img qr.make_image(fill_colorfill_color, back_colorback_color) buffer io.BytesIO() img.save(buffer, formatPNG) b64 base64.b64encode(buffer.getvalue()).decode() return ToolResult( content[ImageContent(typeimage, datab64, mime_typeimage/png)] )这里演示了 FastMCP 工具返回二进制内容的正确姿势用qrcode生成 PIL 图像后写入io.BytesIO以 PNG 格式编码为 base64 字符串返回ToolResult(content[ImageContent(...)])其中mime_typeimage/png明确图像类型。从 tools/base.py 看ToolResult是 FastMCP 工具结果的统一载体包含content内容块列表、structured_content结构化内容、meta与is_error等字段content必须非空且会经过类型适配转换后映射为 MCP 协议的CallToolResult。3. 资源ui://qr-server/view.html与ResourceCSPmcp.resource( VIEW_URI, appAppConfig(cspResourceCSP(resource_domains[https://unpkg.com])), ) def view() - str: Interactive QR code viewer — renders tool results as images. return EMBEDDED_VIEW_HTML与工具不同资源上的AppConfig不设置resource_uri资源本身就是 UI而是声明csp。ResourceCSP的字段定义见 apps/config.py字段别名wire 格式对应 CSP 指令connect_domainsconnectDomainsconnect-srcfetch/XHR/WebSocketresource_domainsresourceDomainsscript-src等脚本、图片、样式、字体frame_domainsframeDomainsframe-src嵌套 iframebase_uri_domainsbaseUriDomainsbase-uri示例中resource_domains[https://unpkg.com]是因为内嵌 HTML 需要从 unpkg CDN 加载modelcontextprotocol/ext-appsSDK——宿主MCP Apps 客户端会依据这些声明为沙箱 iframe 生成对应的Content-Security-Policy头从而允许加载该域名下的脚本。4. 内嵌 HTML 与 MCP Apps JS SDKEMBEDDED_VIEW_HTMLqr_server.py是完整的自包含 HTML 页面核心逻辑如下从 CDN 导入 SDK 并连接script typemodule import { App } from https://unpkg.com/modelcontextprotocol/ext-apps0.4.0/app-with-deps; const app new App({ name: QR View, version: 1.0.0 });页面以 ES Module 方式导入modelcontextprotocol/ext-apps0.4.0的App类创建名为 QR View 的应用实例。接收工具结果并渲染图片app.ontoolresult ({ content }) { const img content?.find(c c.type image); if (img) { const qrDiv document.getElementById(qr); qrDiv.innerHTML ; const allowedTypes [image/png, image/jpeg, image/gif]; const mimeType allowedTypes.includes(img.mimeType) ? img.mimeType : image/png; const image document.createElement(img); image.src data:${mimeType};base64,${img.data}; image.alt QR Code; qrDiv.appendChild(image); } };app.ontoolresult是 SDK 提供的回调当宿主调用generate_qr工具并把结果即ImageContent投递给 UI 后前端从content中取出type image的块用data:image/png;base64,...数据 URI 动态创建img展示。allowedTypes白名单做了 MIME 兜底防止非法类型注入。适配宿主安全区域safe areafunction handleHostContextChanged(ctx) { if (ctx.safeAreaInsets) { document.body.style.paddingTop ${ctx.safeAreaInsets.top}px; document.body.style.paddingRight ${ctx.safeAreaInsets.right}px; document.body.style.paddingBottom ${ctx.safeAreaInsets.bottom}px; document.body.style.paddingLeft ${ctx.safeAreaInsets.left}px; } } app.onhostcontextchanged handleHostContextChanged; await app.connect(); const ctx app.getHostContext(); if (ctx) { handleHostContextChanged(ctx); }通过app.onhostcontextchanged监听宿主上下文变化如移动端刘海屏的安全区域再在app.connect()后主动读取一次getHostContext()做初始适配。页面样式还设置了background: transparent、overflow: hidden保证在宿主 iframe 中呈现为干净的浮层效果。背后的协议机制AppConfig 如何变成线上元数据从源码结构可以还原出完整的实现链路mcp.tool(app...)/mcp.resource(..., app...)把AppConfig实例挂到组件的meta上apps/config.py 中的app_config_to_meta_dict()将AppConfig通过model_dump(by_aliasTrue, exclude_noneTrue)转换为 wire 格式的meta[ui]字典——只序列化显式设置的字段键名使用 camelCase服务端在tools/list、resources/list响应中携带该meta[ui]支持 MCP Apps 的宿主客户端解析meta[ui]将工具与resourceUri对应的 UI 资源关联为 iframe 按csp声明设置 CSP并处理visibilityapp/model决定工具是否暴露给模型。也就是说AppConfig是声明式配置——服务端只负责宣告意图实际的过滤与渲染行为由宿主执行这与 apps/config.py 中is_model_visible对 visibility 语义的说明一致。运行效果与验证启动 HTTP 模式后访问http://localhost:3001或通过支持 MCP Apps 的客户端连接工具侧调用generate_qr传入任意 URL 或文本得到ImageContentbase64 PNGUI 侧宿主渲染ui://qr-server/view.html内嵌页面通过 SDK 接收工具结果在 300×300 的圆角卡片中实时显示二维码安全侧由于声明了resource_domains[https://unpkg.com]宿主可以为沙箱 iframe 正确放行 unpkg CDN 的脚本加载页面因此能顺利初始化 SDK。如需在 MCP 客户端如 Claude Desktop中体验完整流程直接执行cd examples/apps/qr_server uv sync fastmcp install stdio fastmcp.json然后重启客户端即可在工具列表中看到generate_qr并以应用视图打开二维码生成界面。小结qr_server是一个麻雀虽小、五脏俱全的 FastMCP Apps 参考实现。通过这一个示例你可以掌握三条可复用的模式工具↔UI 绑定mcp.tool(appAppConfig(resource_uriui://...))把任意工具挂到交互界面安全声明ResourceCSP的connect_domains/resource_domains/frame_domains/base_uri_domains对应 CSP 各指令让宿主在沙箱 iframe 中安全放行所需外部域名二进制内容返回工具统一以ToolResult(content[ImageContent(...)])返回 base64 编码的图片前端 SDK 通过app.ontoolresult接收并渲染。更完整的 AppConfig/ResourceCSP/ResourcePermissions 字段定义可继续阅读 fastmcp_slim/fastmcp/apps/config.py本仓库的其他 App 示例如 examples/apps/approval、examples/apps/form、examples/apps/file_upload则展示了审批、表单、文件上传等更复杂的交互形态可作为下一步的进阶参考。【免费下载链接】fastmcp The fast, Pythonic way to build MCP servers and clients.项目地址: https://gitcode.com/GitHub_Trending/fa/fastmcp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

SpringBoot+Vue3+MyBatis构建美食推荐系统实践 2026/9/12 2:31:47

SpringBoot+Vue3+MyBatis构建美食推荐系统实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
修复 Actual Budget 中重命名后右键菜单失效问题:React 事件监听与 DOM 节点生命周期的实战剖析 2026/9/12 2:31:47

修复 Actual Budget 中重命名后右键菜单失效问题:React 事件监听与 DOM 节点生命周期的实战剖析

修复 Actual Budget 中重命名后右键菜单失效问题:React 事件监听与 DOM 节点生命周期的实战剖析 【免费下载链接】actual A local-first personal finance app 项目地址: https://gitcode.com/GitHub_Trending/ac/actual 导读 本文以 Actual Budget&#xf…

阅读更多 →
校园奶茶店微信小程序毕业设计:从登录支付到订单管理的全流程实践 2026/9/12 2:31:47

校园奶茶店微信小程序毕业设计:从登录支付到订单管理的全流程实践

校园奶茶店这种选题,在计算机毕业设计里属于典型的“小切口、全流程”项目。小程序端要处理点单、购物车、订单状态,管理端要维护商品库存、统计销量,中间还夹着微信登录、支付回调、消息通知这类绕不开的第三方对接。很多同学做完这个项目&a…

阅读更多 →
系统运维核心指南:从基础设施到自动化工具生态 2026/9/12 2:31:47

系统运维核心指南:从基础设施到自动化工具生态

1. 系统运维到底是什么:先把这个概念掰开揉碎 很多人第一次听到"系统运维"四个字,脑子里浮现的画面往往是:一个程序员坐在电脑前,屏幕上一堆命令行在跑,偶尔敲两下回车,然后对着监控面板发呆。这…

阅读更多 →
等保三级数据库合规选型:ECS自建 vs 瑶池RDS核心差异 2026/9/12 2:31:47

等保三级数据库合规选型:ECS自建 vs 瑶池RDS核心差异

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
论文初稿查AI率完全没必要花钱:2026写作、调研、检测工具搭配直接抄 2026/9/12 2:28:47

论文初稿查AI率完全没必要花钱:2026写作、调研、检测工具搭配直接抄

又到开题和赶稿季,后台被问爆的问题永远是那几个:“用DeepSeek写的论文能查出来吗?”“哪个AIGC检测免费又准?”“ChatGPT写完怎么降AI率?” 这两年工具迭代太快,很多人手里用着大模型,却对检测…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞