如何设计一个既提供绘图Tools又提供example_data的MCP服务器:
架构设计建议
方案1:全部使用Tools(推荐)
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)
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流程(推荐)
- 大模型可以主动调用
get_example_data
获取示例数据 - 大模型拿到数据后,主动调用
create_chart
进行绘图 - 整个过程无需人工干预
方案2流程
- 用户或客户端需要先选择要使用的Resource(example_data)
- 大模型获得数据后,可以主动调用
create_chart
Tool
Python实现示例
from mcp.server import Server
from mcp.types import Tool, Resource
import jsonapp = 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),因为:
- 大模型可以完全自主工作
- 无需人工选择数据
- 工作流程更流畅
- 更符合"让大模型自己调用"的需求
这样大模型就可以:
- 自动获取示例数据
- 自动进行绘图
- 完成整个工作流程