第 23 期 | 图形化思维:Excalidraw MCP 绘图实战

更新于 2026/4/5

🎯 学习目标

  1. 理解 Claude MCP (Multi-Modal Command Protocol) 如何实现终端内的富媒体渲染,特别是针对图形界面的呈现。
  2. 掌握 Excalidraw 的核心 JSON 结构,并理解其作为 AI 生成白板图的理想中间格式。
  3. 学习如何利用 React Server Apps (RSA) 扩展,将 AI 生成的 Excalidraw 数据在终端内部"流式渲染"为交互式图形。
  4. 探索通过自然语言提示(Prompt Engineering)直接驱动 AI 生成和修改架构图、流程图等可视化内容的方法。

📖 核心概念讲解

在传统的命令行界面中,我们习惯于文本输出。然而,随着 AI 助手能力的增强,我们对交互体验的期望也水涨船高。本期我们将深入探讨 Claude 如何超越文本,在终端内部直接“绘制”图形,实现真正的图形化思维。

23.1 Claude MCP 与 React Server Apps (RSA):终端富媒体的基石

Claude 的 MCP (Multi-Modal Command Protocol) 是其实现多模态交互的核心机制。它允许 Claude 不仅仅返回文本,还可以调用工具、执行代码,甚至渲染复杂的 UI 组件。当涉及到在终端内渲染丰富的图形界面时,React Server Apps (RSA) 成为了关键技术。

React Server Apps (RSA) 是一种将 React 组件在服务器端渲染,并将结果以特定协议(如 JSON)传输到客户端(如 Claude 的终端环境)进行显示的架构。与传统的客户端渲染不同,RSA 允许服务器完全控制渲染逻辑和数据流,从而在终端内实现高度定制和动态的 UI。

RSA 的核心优势在于:

  • 服务器端逻辑与渲染分离: AI 可以在服务器端生成 UI 的状态和结构,而无需关心客户端的具体渲染细节。
  • 富媒体支持: 突破纯文本限制,可以在终端内渲染图片、图表、甚至交互式组件。
  • 安全性与控制: 服务器端对渲染内容拥有完全控制权,可以确保安全性和一致性。
  • 低客户端开销: 终端客户端只需解析和显示由服务器端发送的轻量级 UI 描述。

在我们的场景中,Claude 会通过其工具调用机制,触发一个生成 Excalidraw JSON 的逻辑,然后将这个 JSON 数据传递给一个预定义的 RSA 组件。这个 RSA 组件负责将 Excalidraw JSON 渲染成实际的图形,并将其流式传输回 Claude 的终端。

graph LR
    A[用户 Prompt] --> B(Claude AI)
    B -- 调用工具 --> C{DiagramGeneratorTool}
    C -- 生成 Excalidraw JSON --> D[React Server App (Excalidraw Renderer)]
    D -- 渲染并流式传输 UI --> E[Claude 终端]
    E -- 显示图形 --> F[用户看到图形]

23.2 Excalidraw:AI 生成白板图的理想中间格式

Excalidraw 是一款流行的手绘风格白板工具,其最大的特点是其图形数据结构非常简洁且是纯 JSON 格式。这使得它成为 AI 生成和解析图形的绝佳选择。

一个 Excalidraw 图形由一系列 elements 组成,每个 element 都是一个 JSON 对象,描述了图形中的一个组件(如矩形、圆形、文本、箭头等)。这些 elements 包含了位置、大小、颜色、文本内容、连接关系等关键属性。

Excalidraw JSON 的优势:

  • 结构清晰: 易于 AI 理解和生成。
  • 可编程性强: 可以通过代码轻松创建、修改和组合图形元素。
  • 手绘风格: 即使是 AI 生成的图,也具有亲和力,不显得过于冰冷。
  • 跨平台: 可以导出为 SVG、PNG,或在 Excalidraw 应用中直接打开。

当 AI 需要生成一个架构图时,它不再需要生成复杂的 SVG 或图片文件,只需生成符合 Excalidraw 规范的 JSON 数据。随后,这个 JSON 数据会被 RSA 组件接收并渲染。

Excalidraw JSON 示例(简化版):

{
  "type": "excalidraw",
  "version": 2,
  "elements": [
    {
      "id": "A",
      "type": "rectangle",
      "x": 100,
      "y": 100,
      "width": 150,
      "height": 80,
      "strokeColor": "#000000",
      "backgroundColor": "rgba(197,208,230,0.5)",
      "fillStyle": "solid",
      "text": "Web Server"
    },
    {
      "id": "B",
      "type": "rectangle",
      "x": 350,
      "y": 100,
      "width": 150,
      "height": 80,
      "strokeColor": "#000000",
      "backgroundColor": "rgba(239,208,197,0.5)",
      "fillStyle": "solid",
      "text": "Database"
    },
    {
      "id": "C",
      "type": "arrow",
      "x": 250,
      "y": 140,
      "width": 100,
      "height": 0,
      "startBinding": { "elementId": "A", "focus": 0 },
      "endBinding": { "elementId": "B", "focus": 0 },
      "strokeColor": "#000000"
    }
  ],
  "appState": {
    "zoom": { "value": 1 },
    "scrollX": 0,
    "scrollY": 0
  }
}

上述 JSON 描述了一个简单的 Web Server 连接到 Database 的架构图。AI 只需要理解这些基本元素和它们的属性,就可以构建出任意复杂的图形。


💻 模拟 Claude TUI 交互

以下模拟了用户在 Claude TUI 中通过对话生成和修改 Excalidraw 图形的过程。

> 请帮我画一个简单的 Web 应用架构图,包含一个客户端、一个Web服务器和一个数据库。

╭─ Claude ──────────────────────────────╮
│  好的,正在为您生成 Web 应用架构图。                                        │
│                                                                        │
│  思考过程:                                                                 │
│  1. 用户请求生成一个包含客户端、Web服务器和数据库的Web应用架构图。            │
│  2. 识别到需要调用 `generate_excalidraw_diagram` 工具。                     │
│  3. 构造工具参数,将用户描述转化为 Excalidraw JSON 元素的抽象表示。         │
│  4. 调用工具,并等待其返回 Excalidraw JSON 数据。                           │
│  5. 将返回的 Excalidraw JSON 数据传递给 React Server App 渲染器。          │
│                                                                        │
│  <tool_code>                                                           │
│  print(tools.generate_excalidraw_diagram(description="a simple web application architecture with a client, a web server, and a database"))
│  </tool_code>                                                          │
│                                                                        │
│  <tool_result>                                                         │
│  {"type": "excalidraw_data", "data": "..."} // 实际会是完整的 Excalidraw JSON 数据,此处省略
│  </tool_result>                                                        │
│                                                                        │
│  // Claude 收到渲染指令,并通过 RSA 协议在终端内渲染 Excalidraw 图形
│  // 终端内显示一个手绘风格的图:
│  // +-----------------+      +-----------------+      +-----------------+
│  // |     Client      | <--> |   Web Server    | <--> |    Database     |
│  // |  (Browser/App)  |      |   (Node.js/Py)  |      |   (PostgreSQL)  |
│  // +-----------------+      +-----------------+      +-----------------+
│                                                                        │
│  这是您请求的 Web 应用架构图。您希望对此图进行哪些修改或添加?             │
╰───────────────────────────────────────╯

> 在 Web 服务器和数据库之间添加一个缓存层,比如 Redis。

╭─ Claude ──────────────────────────────╮
│  好的,正在为您的架构图添加 Redis 缓存层。                                  │
│                                                                        │
│  思考过程:                                                                 │
│  1. 用户请求在现有图的 Web 服务器和数据库之间添加 Redis 缓存层。            │
│  2. 识别到需要调用 `update_excalidraw_diagram` 工具,传入当前图的 ID 或内容,以及修改指令。
│  3. AI 分析指令,确定如何在 Excalidraw JSON 中插入新的 Redis 元素并调整连接。
│  4. 调用工具,获取更新后的 Excalidraw JSON 数据。                          │
│  5. 将更新后的 Excalidraw JSON 数据传递给 React Server App 渲染器。       │
│                                                                        │
│  <tool_code>                                                           │
│  print(tools.update_excalidraw_diagram(diagram_id="current_diagram_id", update_instruction="add a Redis cache layer between Web Server and Database"))
│  </tool_code>                                                          │
│                                                                        │
│  <tool_result>                                                         │
│  {"type": "excalidraw_data", "data": "..."} // 更新后的 Excalidraw JSON 数据
│  </tool_result>                                                        │
│                                                                        │
│  // 终端内显示更新后的手绘风格图:
│  // +-----------------+      +-----------------+      +---------------+      +-----------------+
│  // |     Client      | <--> |   Web Server    | <--> |     Redis     | <--> |    Database     |
│  // |  (Browser/App)  |      |   (Node.js/Py)  |      |   (Cache)     |      |   (PostgreSQL)  |
│  // +-----------------+      +-----------------+      +---------------+      +-----------------+
│                                                                        │
│  Redis 缓存层已成功添加。还有其他需要调整的地方吗?                      │
╰───────────────────────────────────────╯

> 请将整个架构图导出为 SVG 格式。

╭─ Claude ──────────────────────────────╮
│  好的,正在将当前的 Excalidraw 图形导出为 SVG 格式。                       │
│                                                                        │
│  思考过程:                                                                 │
│  1. 用户请求导出当前图为 SVG 格式。                                        │
│  2. 识别到需要调用 `export_excalidraw_diagram` 工具。                      │
│  3. 构造工具参数,指定导出格式为 SVG。                                     │
│  4. 调用工具,获取 SVG 数据。                                              │
│  5. 将 SVG 数据以文本或文件形式提供给用户。                                │
│                                                                        │
│  <tool_code>                                                           │
│  print(tools.export_excalidraw_diagram(diagram_id="current_diagram_id", format="svg"))
│  </tool_code>                                                          │
│                                                                        │
│  <tool_result>                                                         │
│  {"type": "svg_data", "content": "<svg ...>...</svg>", "filename": "architecture.svg"}
│  </tool_result>                                                        │
│                                                                        │
│  您的架构图已导出为 SVG 格式。您可以将以下内容保存到 `architecture.svg` 文件中:
│  ```svg
│  <svg viewBox="0 0 700 300" width="700" height="300" xmlns="http://www.w3.org/2000/svg" font-family="Virgil, Segoe UI Emoji" font-size="16">
│    <!-- SVG 内容省略,实际会包含完整的 Excalidraw 渲染结果 -->
│    <rect x="10" y="50" width="150" height="80" stroke="#000" fill="rgba(197,208,230,0.5)" rx="4" ry="4"></rect>
│    <text x="40" y="95" style="white-space: pre-wrap;" font-family="Virgil, Segoe UI Emoji">Client</text>
│    <!-- 更多 SVG 元素 -->
│  </svg>
│  ```
│  请问还需要什么帮助吗?
╰───────────────────────────────────────╯

💻 代码演示

本节将展示如何构建一个简化的 React Server App (RSA) 组件来渲染 Excalidraw JSON,以及一个模拟的 Claude 工具定义。

1. React Server App (RSA) 组件骨架

假设我们有一个名为 excalidraw-renderer-app 的 RSA。其 package.json 可能如下:

// excalidraw-renderer-app/package.json
{
  "name": "excalidraw-renderer-app",
  "version": "1.0.0",
  "description": "A React Server App to render Excalidraw JSON in Claude's TUI.",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "@excalidraw/excalidraw": "^0.17.0",
    "express": "^4.18.2",
    "body-parser": "^1.20.2"
  }
}

核心的 index.js(或 App.js)文件会包含一个 React 组件,该组件接收 Excalidraw JSON 数据作为 props,并使用 @excalidraw/excalidraw 库在服务器端渲染。

// excalidraw-renderer-app/index.js (简化版,概念演示)
const express = require('express');
const bodyParser = require('body-parser');
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const Excalidraw = require('@excalidraw/excalidraw').Excalidraw; // 仅用于类型和结构,实际渲染需客户端JS

const app = express();
const PORT = process.env.PORT || 3001;

app.use(bodyParser.json());

// 这是一个概念性的 RSA 端点,实际渲染会更复杂,需要将Excalidraw的客户端JS打包并发送
// Claude 终端会有一个内置的浏览器/渲染器来执行这些JS并显示图形
app.post('/render-excalidraw', (req, res) => {
    const { excalidrawElements, appState } = req.body;

    // 在服务器端,我们不能直接运行浏览器JS来渲染Excalidraw组件
    // 相反,我们会生成一个包含Excalidraw数据的HTML片段,
    // 或者更常见的是,生成一个轻量级的JSON描述,指示Claude终端的内置渲染器如何加载和显示Excalidraw。
    // 以下是模拟的输出结构,实际会是 Claude MCP 协议的一部分。

    // 为了演示,我们假设返回一个特殊格式的 JSON,指示 Claude 终端渲染 Excalidraw
    const mcpCommand = {
        type: "ui_component",
        component: "ExcalidrawViewer", // 终端内置的 Excalidraw 渲染组件名
        props: {
            elements: excalidrawElements,
            appState: appState,
            // 其他 Excalidraw props,如 theme, zenMode 等
        }
    };

    res.json(mcpCommand);
});

app.listen(PORT, () => {
    console.log(`Excalidraw RSA listening on port ${PORT}`);
});

/*
在真实的 Claude 环境中,这个流程是高度抽象和标准化的:
1. Claude 调用工具,该工具生成 Excalidraw JSON。
2. Claude 内部机制识别到这是 Excalidraw JSON,并将其传递给一个预注册的“Excalidraw 渲染器”RSA。
3. RSA 接收 Excalidraw JSON,并将其打包成一个符合 MCP 协议的响应(可能是包含一个 React 组件的描述,或者一个可以直接在终端渲染器中执行的指令)。
4. Claude 终端接收到 MCP 响应后,调用其内置的 Excalidraw 渲染逻辑,将 JSON 数据可视化。
*/

2. 模拟 Claude 工具定义 (Tool Definition)

Claude 需要一个工具来触发 Excalidraw 图形的生成和渲染。这个工具的定义会告诉 Claude 如何调用它,以及它接受哪些参数。

// tools_schema.json
[
  {
    "name": "generate_excalidraw_diagram",
    "description": "Generates a new Excalidraw diagram based on a natural language description and returns the Excalidraw JSON data.",
    "input_schema": {
      "type": "object",
      "properties": {
        "description": {
          "type": "string",
          "description": "A natural language description of the diagram to generate (e.g., 'a simple web architecture with client, server, and database')."
        },
        "theme": {
          "type": "string",
          "enum": ["light", "dark"],
          "description": "The theme for the diagram.",
          "default": "light"
        }
      },
      "required": ["description"]
    }
  },
  {
    "name": "update_excalidraw_diagram",
    "description": "Modifies an existing Excalidraw diagram based on a natural language instruction.",
    "input_schema": {
      "type": "object",
      "properties": {
        "diagram_id": {
          "type": "string",
          "description": "The ID of the diagram to update. This would typically be tracked by Claude or the user."
        },
        "update_instruction": {
          "type": "string",
          "description": "A natural language instruction describing the changes to make (e.g., 'add a Redis cache between server and database')."
        }
      },
      "required": ["diagram_id", "update_instruction"]
    }
  },
  {
    "name": "export_excalidraw_diagram",
    "description": "Exports an existing Excalidraw diagram to a specified format (e.g., SVG, PNG).",
    "input_schema": {
      "type": "object",
      "properties": {
        "diagram_id": {
          "type": "string",
          "description": "The ID of the diagram to export."
        },
        "format": {
          "type": "string",
          "enum": ["svg", "png"],
          "description": "The desired export format.",
          "default": "svg"
        }
      },
      "required": ["diagram_id", "format"]
    }
  }
]

在实际应用中,这些工具的后端实现会负责:

  1. 解析用户描述: 将自然语言描述(descriptionupdate_instruction)转换为 Excalidraw JSON 结构。这可能涉及到复杂的 NLP 和图结构生成逻辑。
  2. 管理图状态: 跟踪当前会话中的图的 diagram_id 和其对应的 Excalidraw JSON 数据,以便进行后续修改和导出。
  3. 返回 Excalidraw JSON: 工具执行成功后,返回包含 Excalidraw JSON 的数据。Claude 接收到这个数据后,会通过其内部机制将其传递给上述的 RSA 渲染器。

🔧 涉及的 Tools / Commands

工具/命令名称 用途 说明
Claude MCP 多模态内容传输协议 Claude 与外部工具和渲染器进行富媒体数据交换的底层协议。它允许 Claude 在终端内显示除文本以外的复杂 UI,如 Excalidraw 图形,通过传递结构化数据和渲染指令实现。
React Server Apps (RSA) 终端内富媒体 UI 渲染框架 基于 React 的服务器端渲染应用,作为 Claude MCP 的一个重要组成部分。它接收 AI 生成的 UI 描述(如 Excalidraw JSON),并在服务器端进行处理,然后将渲染指令或轻量级 UI 描述发送回 Claude 终端,由终端内置的渲染器进行最终呈现。
Excalidraw 手绘风格白板工具及其 JSON 数据格式 一款流行的开源白板工具,其核心优势在于使用简洁的 JSON 格式描述图形元素。AI 可以轻松生成和解析这种格式的数据,使其成为 AI 驱动图形生成的理想中间件。
generate_excalidraw_diagram AI 生成新 Excalidraw 图形的工具 Claude 通过此工具将用户的自然语言描述(如“画一个 Web 架构图”)转换为 Excalidraw JSON 数据。此工具的后端实现负责将语义转化为具体的图形元素及其属性。
update_excalidraw_diagram AI 修改现有 Excalidraw 图形的工具 允许 Claude 根据用户的指令(如“添加一个 Redis 缓存”)修改已生成的 Excalidraw 图形。此工具需要理解上下文,并能精确地在现有 JSON 结构上进行增删改操作。
export_excalidraw_diagram AI 导出 Excalidraw 图形为其他格式的工具 提供将当前显示的 Excalidraw 图形导出为 SVG、PNG 等常见图片格式的功能。这通常涉及到在服务器端利用 Excalidraw 的渲染能力将 JSON 转换为位图或矢量图。
Prompt Engineering 驱动 AI 绘图的自然语言指令 用户与 Claude 交互时输入的自然语言指令,用于指导 AI 生成、修改或导出 Excalidraw 图形。有效的 Prompt Engineering 是获得满意图形结果的关键,需要清晰、具体的描述。

📝 本期要点回顾

  1. MCP 与 RSA 赋能终端富媒体: Claude 的 Multi-Modal Command Protocol (MCP) 结合 React Server Apps (RSA) 技术,使得在终端内部渲染 Excalidraw 这样的复杂图形成为可能,突破了传统文本界面的限制。
  2. Excalidraw JSON 为 AI 绘图而生: Excalidraw 简洁、可编程的 JSON 数据格式是 AI 生成和操作图形的理想中间表示。AI 可以将复杂概念转化为结构化的 JSON,再由 RSA 渲染。
  3. 对话式图形生成与迭代: 通过自然语言对话,用户可以直接指导 Claude 创建和修改 Excalidraw 图形,实现所见即所得的交互式绘图体验。
  4. 工具链协同工作: AI、自定义工具(如 generate_excalidraw_diagram)和 React Server App 渲染器形成一个紧密的工具链,共同完成从自然语言到终端图形的转化。
  5. 图形化思维的未来: 这种能力预示着 AI 助手将从简单的信息提供者转变为强大的可视化助手,极大地提升了技术交流和设计效率,让复杂的概念以更直观的方式呈现。

🔗 参考资料

  1. Excalidraw 官方网站: https://excalidraw.com/ (了解 Excalidraw 的功能和其 JSON 结构)
  2. React Server Components (概念启发): https://react.dev/learn/understanding-your-ui#react-server-components (虽然 React Server Apps 是一个更广义的概念,但可以从 React Server Components 中获取关于服务器端渲染和组件化架构的灵感。)
  3. Anthropic Tool Use 文档 (概念类比): (请查阅最新的 Anthropic Claude Tool Use 官方文档,了解如何定义和使用工具来扩展 Claude 的能力。具体链接可能随版本更新而变化,请访问 Anthropic 开发者门户。)