MCP 服务器现在支持可视化 UI

发布: (2026年2月2日 GMT+8 23:18)
4 分钟阅读
原文: Dev.to

Source: Dev.to

Visual UIs Are Now Possible in MCP Servers的封面图片

MCP 服务器现在可以直接在 Claude Desktop 的聊天窗口中渲染交互式 UI。不再局限于文本响应——可以呈现实际的 HTML、JavaScript、地图、图表,乃至任何内容。

ISS追踪器演示

什么改变

@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"]
    }
  }
}
  1. 重启 Claude Desktop。
  2. 提问:“ISS 在哪里?”

接下来

地图只是开始。仪表盘、图表、表单、数据可视化——任何你能用 HTML 构建的东西,现在都可以在你的 AI 对话中呈现。

你会用它构建什么?

Back to Blog

相关文章

阅读更多 »