ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

MCP Server 用 JSON Schema 描述能力与函数:TaoToken 统一 Key 接入实战大纲

MCP Server 用 JSON Schema 描述能力与函数:TaoToken 统一 Key 接入实战大纲 1. 为什么 MCP Server 的能力声明必须靠 JSON Schema如果你最近在折腾 LLM 工具调用大概率会遇到一个绕不开的问题模型怎么知道你的服务端到底能干什么传统做法是写一段自然语言提示词把函数名、参数、用途一股脑塞进 system prompt。但这种方式在工具数量超过三五个之后就会迅速失控——模型开始编造参数、调用不存在的函数、把可选字段当必填字段传。MCPModel Context Protocol给出的解法是用 JSON Schema 作为服务端与模型之间的语义契约。MCP Server 不把源码交给模型模型唯一能看到的就是tools/list返回的工具列表每个工具包含name、description和inputSchema三个核心字段。其中inputSchema就是一份标准的 JSON SchemaDraft-07它规定了参数名、类型、是否必填、取值范围、枚举选项等约束。这件事和传统 API 的本质区别在于OpenAPI 里的 Schema 是给程序员看的人读懂文档后手写调用代码而 MCP 里的 Schema 是给大模型读的模型基于description理解语义、基于inputSchema生成合规参数并自主决定要不要调用、调用哪一个。换句话说传统 API 的 Schema 约束的是代码MCP 的 Schema 约束的是模型的思考与输出。这篇内容面向正在做 MCP Server 开发、或者准备把已有函数暴露给 LLM 的工程师。我会给出可直接复制的 JSON Schema 模板、TaoToken 统一 Key 的接入配置以及函数注册与调用验证的完整动作。适合谁写过 Python/TypeScript 函数、想让 Claude Code 或 Cline 这类客户端调用自己服务的开发者。2. TaoToken 统一 Key 前置准备与 MCP 接入通道在写 Schema 之前先把调用通道打通。MCP Server 本身是本地进程但模型侧需要一个稳定的 API 入口。我用 TaoToken 作为统一 Key 通道好处是一个 Key 覆盖多家模型切换模型不用改代码MCP Server 里配置一次 Base URL 就行。官网入口在这里https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后在控制台生成 API Key。API 端点固定为https://taotoken.net/api注意这个地址不带任何查询参数直接作为 Base URL 使用。具体要准备三样东西我把它叫做「三件套」配置项值说明Base URLhttps://taotoken.net/api所有模型请求的统一入口API Keysk-开头的一串字符在控制台 API Keys 页面生成Model ID例如claude-sonnet-4-5按你实际使用的模型填写如果你用的是 Claude Code配置方式是在项目根目录或用户目录下创建.claude/settings.json写入环境变量。如果你用的是 Cline则在 MCP 配置里填 Base URL 和 Key。如果你用 Codex则编辑~/.codex/auth.json。这三种客户端我都实测过核心就是三件套填对。拿 Key 的路径进入控制台后点左侧「API Keys」新建一个 Key复制保存。注意 Key 只在创建时完整显示一次关掉页面就看不到了。这一步别偷懒我第一次就是没存重新生成了一个。MCP Server 侧不需要感知 KeyKey 是客户端调用模型时用的。但如果你在 MCP Server 内部也要调用模型做二次处理比如让模型先总结再返回那就需要在服务端环境变量里也配置TAOTOKEN_API_KEY和TAOTOKEN_BASE_URL。我建议统一用环境变量管理别硬编码进代码。3. 可复制的 JSON Schema 模板与函数注册配置这一节是核心。MCP Server 通过tools/list返回工具列表结构是一个tools数组每个元素包含name、description、inputSchema。下面这份模板可以直接改字段用。先看一个文件读取工具的完整 Schema{ name: read_file, description: 读取本地文件内容仅支持 UTF-8 编码的文本文件。当用户需要查看某个文件的具体内容时调用此函数。, inputSchema: { $schema: http://json-schema.org/draft-07/schema#, type: object, required: [file_path], additionalProperties: false, properties: { file_path: { type: string, description: 文件的绝对路径例如 /Users/xxx/test.txt } } } }几个关键点必须说清楚。additionalProperties: false是强制模型不能传多余参数这一条能挡掉大量幻觉参数。required数组列出必填字段模型漏传会被校验拦下。description要写成给模型看的自然语言说清楚「什么时候调用」而不只是「这个函数干什么」。再看一个带高级约束的 shell 执行工具展示pattern、minimum、maximum、enum的用法{ name: run_shell, description: 在本机执行 shell 命令并返回输出。禁止执行删除类命令。当用户需要运行脚本或查看系统信息时调用。, inputSchema: { type: object, required: [command], additionalProperties: false, properties: { command: { type: string, description: 要执行的 shell 指令禁止包含 rm 删除命令, pattern: ^(?!.*rm).*$ }, timeout: { type: integer, description: 命令超时时间单位秒取值范围 5 到 30, default: 10, minimum: 5, maximum: 30 }, output_format: { type: string, enum: [text, json], default: text, description: 输出格式text 为纯文本json 为结构化输出 } } } }pattern用负向断言禁止 rmminimum/maximum限定超时范围enum限定输出格式。这些约束全部由 Schema 完成服务端代码里不需要再手写一堆 if-else 判断参数合法性。如果你用官方 SDK比如mcpPython 包函数注册时把 Schema 作为装饰器参数传入即可。下面是一个最小可运行的注册示例from mcp.server import Server from mcp.types import Tool, TextContent app Server(demo-server) app.list_tools() async def list_tools(): return [ Tool( nameread_file, description读取本地文件内容仅支持 UTF-8 文本文件, inputSchema{ type: object, required: [file_path], additionalProperties: False, properties: { file_path: { type: string, description: 文件绝对路径 } } } ) ] app.call_tool() async def call_tool(name: str, arguments: dict): if name read_file: path arguments[file_path] with open(path, r, encodingutf-8) as f: return [TextContent(typetext, textf.read())]SDK 内部会自动用 Schema 校验入参校验不通过直接抛错不会进到你的业务逻辑。这就是第二层校验——第一层是模型受 Schema 约束生成参数第二层是服务端再校验一次。4. 验证请求与成功结果从 tools/list 到函数执行配置写完必须验证。MCP 的调用流程是Client 发tools/listServer 返回工具列表LLM 读取 Schema 后生成调用参数Server 校验并执行结果返回给模型。第一步验证tools/list返回是否正确。用 MCP Inspector 或者直接发 JSON-RPC 请求curl -X POST http://localhost:8000/mcp \ -H Content-Type: application/json \ -d { jsonrpc: 2.0, id: 1, method: tools/list, params: {} }成功的话你会看到result.tools数组每个工具都带inputSchema。如果inputSchema是空的或者缺字段模型就没法正确生成参数。第二步模拟模型生成调用参数。假设用户说「帮我读取 readme.md」模型应该输出{ name: read_file, arguments: { file_path: /Users/xxx/readme.md } }注意arguments里的字段必须匹配inputSchema。如果模型传了file_path之外的字段additionalProperties: false会直接拒绝。第三步发tools/call请求验证执行curl -X POST http://localhost:8000/mcp \ -H Content-Type: application/json \ -d { jsonrpc: 2.0, id: 2, method: tools/call, params: { name: read_file, arguments: { file_path: /Users/xxx/readme.md } } }成功返回result.content数组里面是文件内容。如果参数不合法会返回isError: true和错误信息。我实测下来Schema 写得越细模型一次调用成功的概率越高。尤其是description里写清楚「什么时候调用」能显著减少模型乱调的情况。第四步在真实客户端里验证。以 Cline 为例在 MCP 配置里填好 Server 地址然后在对话里说「读取 readme.md」观察 Cline 是否自动触发read_file工具。如果没触发多半是description写得太模糊模型没理解这个工具该在什么场景用。5. 本篇常见错误排查401、local proxy failed、reading choices这一节列几个我踩过的坑对照真实报错来排查。报错一401 Unauthorized。这个几乎都是 Key 问题。检查三件套里的 API Key 是否填对Base URL 是否是https://taotoken.net/api注意不要多加斜杠或路径。如果你在 MCP Server 内部也调模型检查环境变量TAOTOKEN_API_KEY是否生效。用echo $TAOTOKEN_API_KEY确认一下。报错二local proxy failed。这个通常出现在客户端配置了本地代理但代理没启动或者 Base URL 写成了localhost但服务没跑起来。先确认 MCP Server 进程是否在监听再确认客户端里的 Base URL 指向的是 TaoToken 的 API 地址而不是本地地址。如果你在客户端里同时配了 MCP Server 地址和模型 API 地址别搞混——MCP Server 是本地进程模型 API 是远程通道。报错三reading choices 相关错误。这个一般出现在模型返回结构不符合预期时比如模型返回了choices字段但解析代码期望的是content。检查你用的 SDK 版本和模型返回格式是否匹配。如果是 MCP 场景检查tools/call的返回是否被正确解析成content数组。报错四OAuth 相关错误。如果你用的客户端要求 OAuth 登录但你的 Key 是 API Key 模式就会冲突。确认客户端配置里选择的是 API Key 认证而不是 OAuth。Claude Code 和 Cline 都支持 API Key 模式在设置里切换即可。报错五Schema 校验失败但没提示具体字段。这是最烦的。建议在服务端加一层日志把收到的arguments原样打印出来再和inputSchema对照。常见原因是模型把integer传成了字符串或者漏传了required字段。additionalProperties: false也会导致模型多传字段时直接失败这时候要么放宽 Schema要么在description里明确告诉模型不要传额外字段。排查顺序建议先确认 Key 和 Base URL再确认 MCP Server 进程再确认 Schema 字段最后看客户端日志。大部分问题出在前两步。6. 语义一致的 CTA 与后续接入建议如果你已经跑通了上面的流程下一步建议把 Schema 模板沉淀成团队规范。我自己的做法是每个工具函数先写description明确「什么时候调用」和「不什么时候调用」再写inputSchema把能加的约束都加上。enum和pattern是性价比最高的两个关键字能挡掉大量无效调用。对于需要长期跑编码任务或 Agent 场景的建议直接用 Coding Plan省去每次手动配 Key 的麻烦。入口在 https://taotoken.net/api-keys 生成 Key 后按上面的三件套配置即可。如果你只是想先验证模型对话效果可以用模型对话页面快速试一下 Schema 描述是否清晰https://taotoken.net/chat 。接入文档在 https://taotoken.net/doc 里面有各客户端的详细配置步骤。Claude Code 的接入可以参考 https://taotoken.net/claude-code Cline 的 MCP 配置参考 https://taotoken.net/cline-mcp 。最后说一个实用技巧Schema 里的description不要写「读取文件」这种泛泛的描述要写成「当用户需要查看某个文件的具体内容时调用此函数仅支持 UTF-8 文本文件」。模型是靠语义匹配来决定调用的描述越具体误触发越少。我试过把同一个函数的 description 从一句话扩成三句话模型调用准确率明显提升。这个细节比调参数管用。
返回列表