如何设计一个既提供绘图Tools又提供example_data的MCP服务器:

架构设计建议

方案1:全部使用Tools(推荐)

javascript 复制代码
const server = new Server({
  name: "chart-generator",
  version: "1.0.0"
}, {
  capabilities: {
    tools: {}
  }
});

// Tool 1: 获取示例数据
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  if (request.params.name === "get_example_data") {
    const dataType = request.params.arguments?.type || "sales";
    
    const exampleData = {
      sales: [
        {month: "Jan", value: 100},
        {month: "Feb", value: 150},
        {month: "Mar", value: 120}
      ],
      temperature: [
        {date: "2024-01-01", temp: 20},
        {date: "2024-01-02", temp: 22},
        {date: "2024-01-03", temp: 18}
      ]
    };
    
    return {
      content: [{
        type: "text",
        text: JSON.stringify(exampleData[dataType])
      }]
    };
  }
  
  // Tool 2: 绘图工具
  if (request.params.name === "create_chart") {
    const { data, chartType, title } = request.params.arguments;
    
    // 处理数据并生成图表
    const chartResult = await generateChart(data, chartType, title);
    
    return {
      content: [{
        type: "text", 
        text: `Chart created successfully: ${chartResult.url}`
      }]
    };
  }
});

// 注册工具
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: "get_example_data",
        description: "获取绘图示例数据",
        inputSchema: {
          type: "object",
          properties: {
            type: {
              type: "string",
              enum: ["sales", "temperature", "population"],
              description: "示例数据类型"
            }
          }
        }
      },
      {
        name: "create_chart",
        description: "根据数据创建图表",
        inputSchema: {
          type: "object",
          properties: {
            data: {
              type: "array",
              description: "图表数据"
            },
            chartType: {
              type: "string",
              enum: ["line", "bar", "pie"],
              description: "图表类型"
            },
            title: {
              type: "string",
              description: "图表标题"
            }
          },
          required: ["data", "chartType"]
        }
      }
    ]
  };
});

方案2:混合模式(Resources + Tools)

javascript 复制代码
const server = new Server({
  name: "chart-generator",
  version: "1.0.0"
}, {
  capabilities: {
    resources: {},
    tools: {}
  }
});

// Resources: 提供示例数据
server.setRequestHandler(ListResourcesRequestSchema, async () => {
  return {
    resources: [
      {
        uri: "data://examples/sales",
        name: "销售数据示例",
        description: "用于演示图表绘制的销售数据",
        mimeType: "application/json"
      },
      {
        uri: "data://examples/temperature", 
        name: "温度数据示例",
        description: "用于演示折线图的温度数据",
        mimeType: "application/json"
      }
    ]
  };
});

server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
  const uri = request.params.uri;
  
  const exampleData = {
    "data://examples/sales": [
      {month: "Jan", value: 100},
      {month: "Feb", value: 150},
      {month: "Mar", value: 120}
    ],
    "data://examples/temperature": [
      {date: "2024-01-01", temp: 20},
      {date: "2024-01-02", temp: 22}, 
      {date: "2024-01-03", temp: 18}
    ]
  };
  
  if (exampleData[uri]) {
    return {
      contents: [{
        uri,
        mimeType: "application/json",
        text: JSON.stringify(exampleData[uri], null, 2)
      }]
    };
  }
  
  throw new Error("Resource not found");
});

// Tools: 绘图功能
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  if (request.params.name === "create_chart") {
    const { data, chartType, title } = request.params.arguments;
    const chartResult = await generateChart(data, chartType, title);
    
    return {
      content: [{
        type: "text",
        text: `Chart created: ${chartResult.url}`
      }]
    };
  }
});

大模型的使用流程

方案1流程(推荐)

  1. 大模型可以主动调用 get_example_data 获取示例数据
  2. 大模型拿到数据后,主动调用 create_chart 进行绘图
  3. 整个过程无需人工干预

方案2流程

  1. 用户或客户端需要先选择要使用的Resource(example_data)
  2. 大模型获得数据后,可以主动调用 create_chart Tool

Python实现示例

python 复制代码
from mcp.server import Server
from mcp.types import Tool, Resource
import json

app = Server("chart-generator")

# 示例数据
EXAMPLE_DATA = {
    "sales": [
        {"month": "Jan", "value": 100},
        {"month": "Feb", "value": 150},
        {"month": "Mar", "value": 120}
    ],
    "temperature": [
        {"date": "2024-01-01", "temp": 20},
        {"date": "2024-01-02", "temp": 22},
        {"date": "2024-01-03", "temp": 18}
    ]
}

@app.list_tools()
async def list_tools():
    return [
        Tool(
            name="get_example_data",
            description="获取绘图示例数据",
            inputSchema={
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": ["sales", "temperature"],
                        "description": "数据类型"
                    }
                }
            }
        ),
        Tool(
            name="create_chart", 
            description="创建图表",
            inputSchema={
                "type": "object",
                "properties": {
                    "data": {"type": "array"},
                    "chart_type": {"type": "string"},
                    "title": {"type": "string"}
                },
                "required": ["data", "chart_type"]
            }
        )
    ]

@app.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "get_example_data":
        data_type = arguments.get("type", "sales")
        return json.dumps(EXAMPLE_DATA.get(data_type, []))
    
    elif name == "create_chart":
        # 实现图表生成逻辑
        data = arguments["data"]
        chart_type = arguments["chart_type"] 
        title = arguments.get("title", "Chart")
        
        chart_url = await generate_chart(data, chart_type, title)
        return f"Chart created: {chart_url}"

建议

推荐使用方案1(全Tools),因为:

  1. 大模型可以完全自主工作
  2. 无需人工选择数据
  3. 工作流程更流畅
  4. 更符合"让大模型自己调用"的需求

这样大模型就可以:

  1. 自动获取示例数据
  2. 自动进行绘图
  3. 完成整个工作流程
相关推荐
芝士加41 分钟前
Playwright vs MidScene:自动化工具“双雄”谁更适合你?
前端·javascript
Carlos_sam2 小时前
OpenLayers:封装一个自定义罗盘控件
前端·javascript
前端南玖2 小时前
深入Vue3响应式:手写实现reactive与ref
前端·javascript·vue.js
用户2018792831673 小时前
通俗易懂的讲解:Android系统启动全流程与Launcher诞生记
android
二流小码农3 小时前
鸿蒙开发:资讯项目实战之项目框架设计
android·ios·harmonyos
Yueyanc3 小时前
LobeHub桌面应用的IPC通信方案解析
前端·javascript
用户2018792831674 小时前
WMS 的核心成员和窗口添加过程
android
麦当_4 小时前
基于 Shadcn 的可配置表单解决方案
前端·javascript·面试
用户2018792831674 小时前
PMS 创建之“软件包管理超级工厂”的建设
android
用户2018792831674 小时前
通俗易懂的讲解:Android APK 解析的故事
android