MCP 服务器现在支持可视化 UI
Source: Dev.to

MCP 服务器现在可以直接在 Claude Desktop 的聊天窗口中渲染交互式 UI。不再局限于文本响应——可以呈现实际的 HTML、JavaScript、地图、图表,乃至任何内容。
什么改变
@modelcontextprotocol/ext-apps 库允许 MCP 工具返回可视化 UI。调用工具时,你不再仅仅收到文本,而是会在对话中内联渲染一个交互式 iframe。
这意味着你的 AI 助手可以向你展示内容,而不仅仅是文字描述。
资源
Source: …
工作原理
架构分为两部分:一个负责获取数据并声明 UI 的服务器,以及一个在客户端渲染 UI 的应用。
服务器端
使用指向 HTML 资源的 UI 元数据注册工具:
import { registerAppTool, registerAppResource } from "@modelcontextprotocol/ext-apps/server";
const resourceUri = "ui://iss-tracker/mcp-app.html";
// 注册 UI 资源(打包的 HTML)
registerAppResource(server, resourceUri, "text/html", () => APP_HTML);
// 使用 UI 元数据注册工具
registerAppTool(server, "where_is_iss", {
description: "在实时地图上显示国际空间站位置",
uiResourceUri: resourceUri,
csp: {
connectDomains: ["https://*.openstreetmap.org", "https://unpkg.com"],
resourceDomains: ["https://*.openstreetmap.org", "https://unpkg.com"],
},
execute: async () => {
const [iss, path, geo] = await Promise.all([
fetch("https://api.wheretheiss.at/v1/satellites/25544").then(r => r.json()),
fetch(`https://api.wheretheiss.at/v1/satellites/25544/positions?timestamps=${timestamps}`).then(r => r.json()),
fetch("http://ip-api.com/json/").then(r => r.json()),
]);
return { iss, path, user: { latitude: geo.lat, longitude: geo.lon, city: geo.city } };
},
});
csp 字段非常重要——它声明了 UI 需要访问的外部域名。如果没有此声明,Leaflet 的瓦片和脚本会被阻止。
客户端
UI 接收工具的结果并进行渲染:
import { App } from "@modelcontextprotocol/ext-apps";
const app = new App({ name: "ISS Tracker", version: "1.0.0" });
app.ontoolresult = (result) => {
const data = result.structuredContent;
// 使用数据更新 UI
updateMap(data.iss, data.user);
};
app.connect();
关键坑点:动态脚本加载
在 srcdoc iframe 中,静态的 <script> 标签不起作用。需要动态加载外部库:
async function loadLeaflet(): Promise<void> {
if (typeof L !== "undefined") return;
// 加载 CSS
const cssLink = document.createElement("link");
cssLink.rel = "stylesheet";
cssLink.href = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.css";
document.head.appendChild(cssLink);
// 加载 JS
return new Promise((resolve, reject) => {
const script = document.createElement("script");
script.src = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.js";
script.onload = () => resolve();
script.onerror = () => reject(new Error("Failed to load Leaflet"));
document.head.appendChild(script);
});
}
这让许多开发者感到意外——如果不以这种方式注入,Leaflet 将无法加载。
亲自尝试
git clone https://github.com/JasonMakes801/iss-tracker-mcp
bun install && bun run build
将以下内容添加到 Claude Desktop 配置文件(~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"iss-tracker": {
"command": "/path/to/bun",
"args": ["/path/to/iss-tracker/dist/index.js", "--stdio"]
}
}
}
- 重启 Claude Desktop。
- 提问:“ISS 在哪里?”
接下来
地图只是开始。仪表盘、图表、表单、数据可视化——任何你能用 HTML 构建的东西,现在都可以在你的 AI 对话中呈现。
你会用它构建什么?
