☰
如何设计一个既提供绘图Tools又提供example_data的MCP服务器:TaoToken统一Key接入与配置骨架
2026/9/28 4:33:46 网站建设 项目流程

1. 为什么要把 example_data 也做成 Tool

先说结论:如果你正在写一个 MCP 服务器,想让大模型自己完成「拿数据 → 画图」这条链路,那把 example_data 做成 Tool 比做成 Resource 更省心。原因很直接——Tool 是模型可以主动调用的,Resource 通常需要客户端或用户先选中,模型才能读到内容。

我见过不少同学第一次写 MCP 服务器时,习惯性把示例数据塞进 Resource,觉得「数据嘛,静态的,放 Resource 天经地义」。结果联调时发现,模型画图前总要等用户手动选一下数据源,整个自动化流程断成两截。这不是模型不聪明,是能力边界没设计对。

MCP 服务器(Model Context Protocol Server)本质上是给 AI 工具暴露一组可调用的能力。它通过tools、resources、prompts三类能力与客户端通信。绘图场景里,create_chart显然是 Tool,因为它有副作用、有参数、要返回结果;而example_data到底算 Tool 还是 Resource,取决于你希望谁来触发它。

适合谁看这篇:正在用 Node.js 或 Python 写 MCP 服务器、需要让 AI 稳定调用绘图能力、并且希望把模型接入通道统一管理的开发者。下面我会给出可复制的config.toml与settings.json骨架,再演示一次 Tools 调用和 example_data 返回的完整验证动作。

2. TaoToken 统一 Key 接入:把模型通道先固定下来

MCP 服务器本身不负责「模型从哪来」,它只负责暴露能力。真正让模型跑起来、并且能稳定调用你这些 Tool 的,是背后的模型接入通道。这里我用 TaoToken 做统一入口,好处是一个 Key 覆盖对话、编码、Agent 多类场景,配置一次到处复用。

官网地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 基址是 https://taotoken.net/api ,注意 API 地址不带 UTM 参数,写配置时别把查询串带进去。

你需要先拿到 Key。进入控制台创建:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,然后在 API Keys 页面生成:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。生成后复制那串sk-开头的字符串,后面配置里要用。

如果你打算长期跑编码类或 Agent 类任务,可以看下 Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite ,它更适合高频调用场景。只是想先验证模型能不能正常对话,用模型对话页更快:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。

注意:Key 只放在本地配置文件或环境变量里,不要硬编码进提交到 Git 的源码。下面骨架里我用占位符sk-xxxx,你替换成自己的。

3. 可复制配置骨架:config.toml 与 settings.json

这一节是全文的核心,配置写对了,后面验证基本不会翻车。我分成两块:一块是 MCP 服务器自身的声明(config.toml),一块是客户端侧的接入设置(settings.json)。

3.1 config.toml:声明服务器与模型通道

# config.toml # MCP 服务器基础声明 + TaoToken 统一通道 [server] name = "chart-generator" version = "1.0.0" # 同时开启 tools 能力;example_data 也走 tools capabilities = ["tools"] [server.transport] # 本地开发用 stdio,最省事 type = "stdio" [model] # TaoToken 统一入口,注意 API 地址不带 UTM base_url = "https://taotoken.net/api" api_key = "sk-xxxx" # 按你实际使用的模型名填写 model = "claude-sonnet" [model.retry] max_attempts = 3 backoff_ms = 800 [tools.get_example_data] description = "获取绘图示例数据" data_types = ["sales", "temperature", "population"] [tools.create_chart] description = "根据数据创建图表" chart_types = ["line", "bar", "pie"]

几个容易写错的地方:capabilities里如果只写tools,那 example_data 就必须是 Tool,不能是 Resource,否则客户端列不出来。base_url结尾不要加斜杠,也不要拼/v1之类的后缀,具体路径由 SDK 处理。

3.2 settings.json:客户端接入设置

{ "mcpServers": { "chart-generator": { "command": "node", "args": ["dist/index.js"], "env": { "TAOTOKEN_BASE_URL": "https://taotoken.net/api", "TAOTOKEN_API_KEY": "sk-xxxx" } } }, "model": { "provider": "taotoken", "baseUrl": "https://taotoken.net/api", "apiKey": "sk-xxxx", "model": "claude-sonnet" } }

command和args指向你编译后的入口文件。如果你用 Python 写,就换成python加脚本路径。env里放 Key,代码里用process.env.TAOTOKEN_API_KEY读取,这样配置和代码解耦。

3.3 两个 Tool 的注册骨架

// 只保留关键结构,方便你对照 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"] }, title: { type: "string" } }, required: ["data", "chartType"] } } ] }; });

inputSchema里的enum很关键,它等于给模型画了可选范围,模型乱传参数的概率会明显下降。required只写真正必需的字段,title这种可选的别加进去,否则模型每次都得编一个标题。

4. 验证请求:一次 Tools 调用 + example_data 返回

配置写完,别急着接大流程,先做最小验证。我习惯分两步:先确认 example_data 能返回,再确认 create_chart 能拿到数据并出图。

4.1 验证 example_data 返回

启动服务器后,在客户端里发一条调用请求,参数type传sales:

{ "method": "tools/call", "params": { "name": "get_example_data", "arguments": { "type": "sales" } } }

预期返回是一段 JSON 文本,内容形如:

[ { "month": "Jan", "value": 100 }, { "month": "Feb", "value": 150 }, { "month": "Mar", "value": 120 } ]

如果返回的是空数组,先检查type是否落在enum范围内,再检查你的EXAMPLE_DATA字典键名和enum是否一致。我踩过的坑就是键名写成Sales大写,模型传sales小写,结果一直返回空。

4.2 验证 create_chart 调用

拿到数据后,把这段数组直接喂给create_chart:

{ "method": "tools/call", "params": { "name": "create_chart", "arguments": { "data": [ { "month": "Jan", "value": 100 }, { "month": "Feb", "value": 150 }, { "month": "Mar", "value": 120 } ], "chartType": "bar", "title": "季度销售" } } }

成功时返回类似Chart created successfully: <url>的文本。这里的<url>是你绘图逻辑产出的地址,本地开发可以先返回一个占位路径,确认链路通了再换成真实存储。

4.3 让模型自己串起来

两步都通之后,把「先调 get_example_data,再调 create_chart」写进系统提示或工具描述里。因为两个都是 Tool,模型可以自主完成,不需要用户中途选数据。这就是全 Tools 方案的价值:流程不断档。

5. 本篇常见错排查

下面这些是我在联调时真实遇到过的,按出现频率排。

报错一:Tool not found: get_example_data多半是ListToolsRequestSchema里没注册这个 Tool,或者capabilities只写了resources。检查config.toml的capabilities是否包含tools。

报错二:模型传参chartType为空inputSchema里chartType没写进required,模型可能省略。把它加进required数组即可。

报错三:401 或鉴权失败Key 没读到。确认settings.json的env里TAOTOKEN_API_KEY拼写正确,代码里读取的变量名一致。另外确认base_url是https://taotoken.net/api,不要带多余路径。

报错四:example_data 返回字符串而非数组JSON.stringify之后模型拿到的是文本,这是正常的。如果你希望模型直接当数组用,在 Tool 描述里说明「返回 JSON 字符串,需解析后使用」。

报错五:绘图 Tool 超时绘图逻辑本身耗时,建议在create_chart里加超时和降级返回,别让整个 MCP 请求卡死。config.toml里的retry只对模型通道生效,Tool 内部逻辑要自己兜底。

提示:排障阶段建议把服务器日志级别调高,把每次tools/call的入参和返回都打出来,定位问题快很多。

6. 接入通道与后续动作

配置和验证都跑通后,接下来就是把它接到真实工作流里。如果你主要在做排障和接入调试,重点看 API Keys 和接入文档:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite ,文档入口在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。

想先确认模型对话是否正常,用模型对话页试一条:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。如果你要长期跑编码或 Agent 类任务,Coding Plan 更合适:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。用 Claude Code 这类工具接入的话,参考 Anthropic 接入说明:https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claude-code-anthropic&utm_campaign=rewrite 。

最后留一个实用建议:把get_example_data的返回结构固定成[{x, y}]这种通用格式,而不是{month, value}这种业务字段。这样你的绘图 Tool 不用为每种数据类型写适配逻辑,模型也更容易理解。等你要接真实数据源时,只要替换数据获取层,Tool 签名和绘图逻辑都不用动。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询