ARTICLE DETAIL

资讯详情

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

MCP化实践:从特征提炼到封装,用TaoToken统一Key打通JSON-RPC与stdio

MCP化实践:从特征提炼到封装,用TaoToken统一Key打通JSON-RPC与stdio 1. 为什么要把现有能力 MCP 化你可能已经有一堆内部工具查日志的脚本、调数据的小接口、跑批的定时任务。它们平时靠人手动执行或者被某个固定系统调用。现在想让大模型代理直接“发现并调用”这些能力最省事的路径不是给每个模型写一套适配层而是把它们封装成 MCP 服务器。MCP 全称 Model Context Protocol它做的事情可以用一句话说清把外部能力标准化成 JSON-RPC 2.0 接口让 AI 客户端通过统一协议发现工具、读取资源、执行调用。它解决的是 N×M 集成问题——不用为每个模型配一个连接器写一次 MCP ServerClaude、GPT 系客户端、各类 Agent 框架都能接。适合 MCP 化的服务有几个共同特征调用频率高、参数简单能用自然语言描述、有明确的输入输出结构、兼具读和写操作。反过来说参数超过七八个、返回体巨大、需要复杂会话状态的服务直接封装效果往往不好得先做一层裁剪。这篇按完整链路走先提炼工具特征再封装成 JSON-RPC 服务覆盖 stdio 与 Streamable HTTP/SSE 两种传输最后用 TaoToken 统一 Key 接入并本地验证。目标是你照着能跑通从封装到联调的闭环。2. TaoToken 前置统一 Key 与接入点在封装之前先把 Key 的事情理清楚。MCP Server 本身不绑定某一家模型但你在本地验证、或者让 Agent 调用工具时需要一个统一的模型入口。TaoToken 在这里的角色是提供兼容 OpenAI 风格的 API 入口一个 Key 走通对话与工具调用省去在多个平台之间切换配置。你需要先拿到 API Key。进入控制台创建https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite创建后在 API Keys 页面复制密钥形如sk-开头。接入文档在这里包含 base_url 与各语言示例https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewriteAPI 基础地址统一用https://taotoken.net/api注意这个地址不带任何查询参数配置里直接写死即可。Key 的管理页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite如果你后面要做长期编码或 Agent 类任务可以了解 Coding Plan它更适合高频调用场景https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite想先在网页里验证模型是否通用模型对话入口https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite把 Key 存到环境变量后面所有配置都引用它避免硬编码export TAOTOKEN_API_KEYsk-你的密钥 export TAOTOKEN_BASE_URLhttps://taotoken.net/api3. 从特征提炼到 JSON-RPC 封装3.1 提炼工具特征拿一个具体例子你有一个内部“订单查询”接口原本是 HTTP GET参数是订单号和用户 ID。要 MCP 化先做特征提炼判断它能不能成为一个好工具。判断维度我一般看四条参数是否少于 5 个、是否能用一句话描述用途、返回是否结构化、是否高频。订单查询满足前三条参数就两个返回 JSON适合封装。如果是一个需要传 12 个筛选条件的报表接口就得先拆成几个语义清晰的子工具否则代理选不准。提炼完写成工具清单每个工具包含 name、description、inputSchema。description 要写清楚“什么时候用”不是“这是什么”。比如不要写“查询订单”要写“根据订单号和用户 ID 查询订单状态与金额用户询问订单进度时调用”。3.2 JSON-RPC 服务骨架MCP 底层是 JSON-RPC 2.0核心方法有initialize、tools/list、tools/call。手写一个最小 server 能帮你理解协议但生产里建议用官方 SDK。下面用 Python 的mcp库写一个可运行的骨架。先装依赖pip install mcp[cli] httpx服务代码order_server.pyimport os import httpx from mcp.server.fastmcp import FastMCP mcp FastMCP(order-service) UPSTREAM https://internal.example.com/order API_KEY os.environ[TAOTOKEN_API_KEY] mcp.tool() async def query_order(order_id: str, user_id: str) - dict: 根据订单号和用户 ID 查询订单状态与金额。 当用户询问订单进度、支付状态或订单金额时调用。 参数 order_id 为订单编号user_id 为用户标识。 async with httpx.AsyncClient(timeout10) as client: resp await client.get( UPSTREAM, params{order_id: order_id, user_id: user_id}, headers{Authorization: fBearer {API_KEY}}, ) resp.raise_for_status() data resp.json() return { order_id: data[id], status: data[status], amount: data[amount], } if __name__ __main__: mcp.run()这里mcp.tool()装饰器自动把函数签名转成 JSON Schemadocstring 变成工具描述。返回体做了裁剪只留代理需要的字段避免把上游几十个字段全塞回去。3.3 stdio 与 Streamable HTTP/SSE 两种传输stdio 传输适合本地进程客户端启动 server 子进程通过标准输入输出通信。上面的mcp.run()默认就是 stdio。它的优点是零网络配置、启动快适合个人开发机和桌面客户端。Streamable HTTP 适合远程部署客户端通过 HTTP POST 发 JSON-RPC 请求服务端可以返回单次响应或 SSE 流。切换方式if __name__ __main__: mcp.run(transportstreamable-http, host0.0.0.0, port8000)启动后端点默认在http://localhost:8000/mcp。SSE 流式响应用于工具执行时间较长、需要边执行边推送进度的场景。如果你的工具是秒级返回用普通 JSON 响应即可不必强上 SSE。两种传输的取舍本地调试用 stdio团队共享或云端部署用 Streamable HTTP。协议层一致工具定义不用改只换 transport 参数。4. 可复制配置settings.json 与 config.toml4.1 Claude Desktop 风格 settings.json很多客户端用 JSON 配置 MCP Server。stdio 方式{ mcpServers: { order-service: { command: python, args: [/abs/path/order_server.py], env: { TAOTOKEN_API_KEY: sk-你的密钥 } } } }Streamable HTTP 方式{ mcpServers: { order-service: { url: http://localhost:8000/mcp, headers: { Authorization: Bearer sk-你的密钥 } } } }注意 stdio 配置里args用绝对路径相对路径在不同客户端工作目录下容易找不到文件这是高频踩坑点。4.2 config.toml 风格部分工具链用 TOML。等价配置[[mcp_servers]] name order-service transport stdio command python args [/abs/path/order_server.py] [mcp_servers.env] TAOTOKEN_API_KEY sk-你的密钥HTTP 版本[[mcp_servers]] name order-service transport streamable-http url http://localhost:8000/mcp [mcp_servers.headers] Authorization Bearer sk-你的密钥提示Key 尽量走环境变量注入配置文件里写占位符提交到仓库前检查一遍避免密钥泄露。5. 验证请求与成功结果5.1 用 MCP Inspector 本地验证官方 Inspector 能模拟客户端交互最直观npx modelcontextprotocol/inspector python /abs/path/order_server.py打开它给出的本地地址在 Tools 面板点list tools应该看到query_order及其 schema。再点call tool填入{order_id: 20250101-001, user_id: u_123}成功时返回{ order_id: 20250101-001, status: paid, amount: 199.00 }5.2 直接发 JSON-RPC 请求验证 HTTP 传输server 以 streamable-http 启动后用 curl 验证curl -X POST http://localhost:8000/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -d { jsonrpc: 2.0, id: 1, method: tools/list, params: {} }返回里应包含result.tools数组。再调tools/callcurl -X POST http://localhost:8000/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -d { jsonrpc: 2.0, id: 2, method: tools/call, params: { name: query_order, arguments: {order_id: 20250101-001, user_id: u_123} } }看到result.content里带文本结果说明链路通了。注意Accept头必须同时包含application/json和text/event-stream只写一个会被部分实现拒绝。5.3 用 TaoToken 验证模型侧工具调用工具通了还要确认模型能正确选择它。用兼容 OpenAI 的调用方式把工具 schema 传进去import os from openai import OpenAI client OpenAI( api_keyos.environ[TAOTOKEN_API_KEY], base_urlhttps://taotoken.net/api, ) tools [{ type: function, function: { name: query_order, description: 根据订单号和用户 ID 查询订单状态与金额, parameters: { type: object, properties: { order_id: {type: string}, user_id: {type: string}, }, required: [order_id, user_id], }, }, }] resp client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: 帮我查下订单 20250101-001用户 u_123}], toolstools, ) print(resp.choices[0].message.tool_calls)如果返回里出现tool_calls且function.name是query_order、arguments 解析正确说明模型侧识别成功。这一步跑通整个闭环就成立了。6. 本篇常见错排查报错Method not found: tools/list多半是客户端连到了旧版 SSE 端点或者 server 没实现tools/list。检查 transport 是否与客户端期望一致stdio 客户端不要连 HTTP 地址。stdio 启动后立即退出常见原因是脚本里有print输出污染了标准输出。stdio 传输下 stdout 只用于 JSON-RPC 消息任何调试打印都会破坏协议。把调试信息改到 stderr或用 logging。HTTP 请求返回 406Accept头没带全。Streamable HTTP 要求同时接受application/json和text/event-stream补上即可。工具调用参数解析失败inputSchema 里类型写错比如把数字写成 string。用 Pydantic 模型定义参数能自动生成正确 schema减少手写错误。Key 无效 401确认 base_url 是https://taotoken.net/api不要多加路径或参数确认 Key 从控制台复制完整没有多余空格。Key 管理入口https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite远程部署后本地能连、外部连不上检查 host 是否绑到0.0.0.0防火墙是否放行端口反向代理是否透传了Accept头。工具返回体过大导致代理卡顿上游返回几十个字段时在 server 里做字段裁剪只返回代理决策需要的部分。这一步不做后面调优会很痛苦。7. 继续接入与下一步到这里你已经跑通了提炼、封装、双传输配置、本地验证的完整链路。接下来如果要把这套东西接到真实客户端里长期用建议先把 Key 和接入文档过一遍确认 base_url 与鉴权方式https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite如果只是想在网页里快速验证模型对工具描述的理解用模型对话入口最省事https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite要做长期编码或 Agent 类高频任务Coding Plan 更合适https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite我自己的习惯是每封装一个新工具先用 Inspector 验证 schema再用 curl 验证 HTTP 传输最后用模型侧调用确认工具选择准确。三步都过才接到生产客户端。这样出问题时能快速定位是协议层、传输层还是模型理解层不用在一堆日志里瞎猜。
返回列表