恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

动手写个agent(四):用Go实现MCP协议接入TaoToken

  • 首页
  • 资讯中心
  • /
  • 动手写个agent(四):用Go实现MCP协议接入TaoToken

相关资讯

节前最后一波实测,最新模型MiniMax M2.5接入TaoToken统一Key实战 2026/10/7 19:25:26
使用Python链接MySQL及Redis缓存型数据库:TaoToken统一Key通道下的连接配置与读写验证 2026/10/7 19:25:26
在线客服系统源码选型:微信支付与图文回复的实战避坑指南 2026/10/7 19:25:26

最新资讯

Agent Platform超时故障根因与高可用改造实践
FLIP动画技术解析:用transform优化布局动画,告别掉帧卡顿
ArcGIS Portal接入天地图底图:WMTS配置与排查实操
ArcGIS Portal接入天地图底图:密钥申请、WMTS配置与代理注入全攻略
Linux常用命令与操作详解:从排障到脚本的体系化实战
2026企业网盘安全横评:谁真能防删库跑路与勒索病毒?

今日推荐

SSD不认盘怎么修?金士顿SV300板级排查与短接ROM进工厂模式
Unity 3D RPG开发:C#状态机与物理更新时机实战指南
AIoT开发工程师岗位全景:从嵌入式Linux到边缘计算与端侧AI部署

本周热门

MR25H40CDF + PIC18F65K40:工业记录仪高可靠存储实战
基于STM32的数控恒压恒流电源设计:从硬件到PID调参全解析
LT9211 MIPI重定时器原理与双路扇出实战指南

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

动手写个agent(四):用Go实现MCP协议接入TaoToken

发布时间:2026/10/7 19:25:26
动手写个agent(四):用Go实现MCP协议接入TaoToken 1. 从零写 Agent 时工具越加越乱怎么办写 Agent 写到第四篇最容易卡住的不是模型调用而是工具管理。前几篇里我们给 Agent 加了 shell 工具、时间工具每加一个就要改一次主程序注册表越写越长main.go里堆满了toolRegistry.Register(...)。更麻烦的是工具的实现和 Agent 的核心循环绑死了想换一个文件操作实现得动 Agent 的代码。这个问题的本质是耦合。Agent 负责思考循环工具负责具体执行两者本该独立演进却因为直接函数调用被焊在一起。解决办法在软件工程里很经典加一层抽象。让 Agent 和工具之间用一套标准协议对话只要双方都遵守协议谁都不用关心对方内部怎么实现。这套协议就是 MCPModel Context Protocol模型上下文协议。你可以把它理解成 USBU 盘、鼠标、键盘只要符合 USB 规范插到任何电脑上都能用电脑不需要为每个设备装专用驱动。在 MCP 里Agent 是那台电脑各种工具服务是 USB 设备。MCP 基于 JSON-RPC 2.0所有交互都是结构化的 JSON 消息。核心流程就四步连接后发initialize握手问对方是谁、支持什么能力发tools/list拿到工具清单把工具清单喂给 LLMLLM 决定调用时发tools/call带上工具名和参数拿到结果继续循环。传输方式官方定义两种。stdio 适合本地可执行程序Server 作为 Client 的子进程JSON-RPC 消息写进子进程 stdin从 stdout 读响应。HTTP/SSE 适合远程服务先建 SSE 长连接服务端下发 endpoint 事件告诉客户端往哪 POST 请求。这篇要做的就是用 Go 从零实现一个 MCP 客户端解析 JSON-RPC 消息完成工具注册与调用链路最后用 TaoToken 的统一 Key 跑通整个工具调用流程。适合已经写过基础 Agent、想引入标准化工具生态的 Go 开发者。下面所有代码都可以直接复制进你的项目。2. 用 TaoToken 统一 Key 接入 MCP 工具调用链路在动手写 MCP 客户端之前先把模型接入这块理顺。MCP 解决的是工具怎么插拔但工具调用最终还是要 LLM 来决定调哪个、传什么参数。也就是说Agent Loop 里必须有一个稳定的模型入口能返回标准的 tool_calls 结构。我试过在多个项目里分别维护不同厂商的 Key 和 Base URL切换模型时改配置改到崩溃。后来统一走 TaoToken一个 Key 覆盖多种模型Base URL 固定Agent 侧只需要改 model 字段就能换模型MCP 工具链路完全不用动。TaoToken 在这里的角色是模型能力的统一入口。它的 API 地址是https://taotoken.net/api兼容 OpenAI 的 chat completions 格式返回的tool_calls字段结构标准正好对接我们 MCP 客户端注册进来的工具。你不需要为每个模型单独写适配层Agent 的 LLM 客户端只认一套请求响应格式。具体来说MCP 客户端负责把工具清单整理成 OpenAI function calling 需要的 JSON SchemaLLM 返回 tool_calls 后Agent 根据工具名前缀找到对应的 MCP Server转发tools/call请求。TaoToken 保证的就是这个 LLM 环节的稳定输出。配置上你需要在项目里准备一个 config.json把模型接入信息和 MCP Server 配置放一起。模型部分填 TaoToken 的 Base URL 和 KeyMCP 部分填你要接入的工具服务。这样 Agent 启动时一次性加载模型和工具都从配置来代码里不写死任何厂商信息。有一点要注意MCP 工具的 InputSchema 是 JSON Schema 格式和 OpenAI function calling 的 parameters 格式基本一致但个别字段命名有差异比如 MCP 用inputSchemaOpenAI 用parameters。适配器里要做一次转换这个后面代码里会体现。如果你还没拿 Key可以去 TaoToken 控制台创建一个然后在 API Keys 页面复制。接入文档里有完整的请求示例对照着填 config.json 就行。模型对话页面可以先手动测一下 tool_calls 返回结构确认格式没问题再写进 Agent。3. 可复制的 Go 模块配置与 MCP 握手代码先把项目结构和依赖定下来。我们用 Go modules 管理核心依赖是 zerolog 做日志其余标准库够用。go.mod 长这样module chapter4 go 1.21 require ( github.com/rs/zerolog v1.32.0 )MCP 客户端的核心是 JSON-RPC 消息封装。先定义请求和响应结构字段名严格按 JSON-RPC 2.0 规范来package transport // Request JSON-RPC 2.0 请求 type Request struct { JSONRPC string json:jsonrpc ID int64 json:id Method string json:method Params interface{} json:params,omitempty } // Response JSON-RPC 2.0 响应 type Response struct { JSONRPC string json:jsonrpc ID int64 json:id Result json.RawMessage json:result,omitempty Error *RPCError json:error,omitempty } type RPCError struct { Code int json:code Message string json:message }握手是第一步。Client 连接后发initialize带上协议版本和客户端能力Server 返回它支持的能力集func (c *Client) initialize(ctx context.Context) error { params : map[string]interface{}{ protocolVersion: 2024-11-05, capabilities: map[string]interface{}{ tools: map[string]interface{}{}, }, clientInfo: map[string]string{ name: go-agent, version: 1.0.0, }, } resp, err : c.sendRequest(ctx, initialize, params) if err ! nil { return fmt.Errorf(initialize 失败: %w, err) } // 握手成功后发送 initialized 通知 c.sendNotification(notifications/initialized, nil) return c.parseServerCapabilities(resp.Result) }握手完成后拉工具列表tools/list返回的每个工具包含 name、description、inputSchemafunc (c *Client) fetchTools(ctx context.Context) error { resp, err : c.sendRequest(ctx, tools/list, nil) if err ! nil { return err } var result struct { Tools []Tool json:tools } if err : json.Unmarshal(resp.Result, result); err ! nil { return err } c.tools result.Tools return nil }工具调用走tools/call参数是工具名加 argumentsfunc (c *Client) CallTool(ctx context.Context, name string, args map[string]interface{}) (*ToolsCallResult, error) { params : map[string]interface{}{ name: name, arguments: args, } resp, err : c.sendRequest(ctx, tools/call, params) if err ! nil { return nil, err } var result ToolsCallResult if err : json.Unmarshal(resp.Result, result); err ! nil { return nil, err } return result, nil }stdio 传输的实现要点启动子进程把 stdin 包成 writerstdout 包成 bufio.Scanner 按行读。每条 JSON-RPC 消息一行读到就解析。这里有个坑Server 可能输出非 JSON 的日志到 stdout解析失败要跳过而不是直接报错。func (t *StdioTransport) readLoop() { scanner : bufio.NewScanner(t.stdout) scanner.Buffer(make([]byte, 1024*1024), 1024*1024) for scanner.Scan() { line : scanner.Bytes() var resp Response if err : json.Unmarshal(line, resp); err ! nil { continue // 跳过非 JSON 输出 } t.dispatch(resp) } }Manager 负责管理多个 Server 连接聚合所有工具。适配器把 MCP 工具包装成本地 Tool 接口Execute 时转发给 Managerfunc (a *MCPToolAdapter) Execute(ctx context.Context, params json.RawMessage) (string, error) { var arguments map[string]interface{} if err : json.Unmarshal(params, arguments); err ! nil { return , fmt.Errorf(参数解析失败: %w, err) } result, err : a.manager.CallTool(ctx, a.serverName, a.tool.Name, arguments) if err ! nil { return , err } return formatResult(result), nil }config.json 里把 TaoToken 接入和 MCP Server 配置放一起{ base_url: https://taotoken.net/api, api_key: 你的TaoToken Key, model: claude-3-5-sonnet, temperature: 0.7, max_tokens: 10000, timeout: 120, mcp_server_config: [ { name: filesystem, transport: stdio, command: npx, args: [-y, modelcontextprotocol/server-filesystem, ./], enabled: true } ] }注意 Base URL 填https://taotoken.net/api不要带多余路径。Model ID 按你实际用的填TaoToken 支持多种模型换模型只改这一行。4. 验证 MCP 工具调用是否跑通配置写完跑一次完整链路验证。main 函数里初始化 Manager、连接所有 Server、注册工具、启动 Agent Loopfunc main() { config, err : loadConfig(./config.json) if err ! nil { log.Fatal().Err(err).Msg(加载配置失败) } client : llm.NewOpenAIClient(config) toolRegistry : tool.NewRegistry() manager : mcp.NewManager() for _, server : range config.MCPServerConfig { manager.AddServer(server) } if err : manager.ConnectAll(context.Background()); err ! nil { log.Warn().Err(err).Msg(部分 MCP Server 连接失败) } toolRegistry.RegisterMCPTools(manager) myAgent : agent.NewAgent(MyAgent, , 10, client, toolRegistry) answer, err : myAgent.Run(context.Background(), 用 filesystem 工具在当前目录写一个 hello.txt内容为 hello mcp) if err ! nil { log.Fatal().Err(err).Msg(运行 Agent 失败) } fmt.Println(answer) }运行后你应该看到三段日志。第一段是 MCP 初始化每个 Server 打印[MCP] 尝试连接和握手成功。第二段是工具注册[MCP] 已注册工具后面跟着工具名比如mcp_filesystem_write_file。第三段是 Agent LoopLLM 返回 tool_callsAgent 转发给 ManagerManager 找到对应 Client 发tools/call。成功的结果是当前目录出现 hello.txt内容为 hello mcp。同时控制台会打印工具调用结果格式类似Pipeline deploy-frontend 状态: SUCCESS 开始时间: 2026-03-26T10:00:00Z 结束时间: 2026-03-26T10:05:23Z如果你接的是 git 工具可以让 Agent 执行「写一首诗到 a.txt 并用 git 提交」观察它依次调用 writeFile、stage、commit 三个工具。每个工具调用都是一次完整的 JSON-RPC 往返日志里能看到 request 和 response 的 id 对应关系。验证模型侧的时候可以单独用 curl 测一下 TaoToken 的 tool_calls 返回curl https://taotoken.net/api/chat/completions \ -H Authorization: Bearer 你的Key \ -H Content-Type: application/json \ -d { model: claude-3-5-sonnet, messages: [{role: user, content: 写个文件}], tools: [{type: function, function: {name: write_file, parameters: {type: object, properties: {path: {type: string}}}}}] }返回里如果有tool_calls数组说明模型侧链路通了。这一步能快速区分是模型接入问题还是 MCP 客户端问题。5. 常见报错排查401、local proxy failed、reading choices跑 MCP 接入最容易撞几类错逐个说。401 Unauthorized。这个基本是 Key 问题。检查 config.json 里api_key有没有填对有没有多余空格。TaoToken 的 Key 在控制台 API Keys 页面复制注意不要复制到别的字段。如果 Key 没问题还报 401看 Base URL 是不是写成了https://taotoken.net/api/带尾斜杠有些客户端拼接路径时会出问题去掉尾斜杠。local proxy failed。这个错通常出现在 stdio 传输启动子进程时。原因可能是 command 找不到比如npx不在 PATH 里或者 args 里的包名拼错。排查方法先在终端手动跑一遍npx -y modelcontextprotocol/server-filesystem ./看能不能启动。如果手动能跑代码里报错检查 exec.Command 的 Dir 字段有没有设对工作目录。reading choices 相关报错。这个一般出在 LLM 响应解析阶段。TaoToken 返回的是标准 OpenAI 格式choices[0].message.tool_calls是数组。如果你的解析代码假设choices一定存在且非空遇到模型返回纯文本没调工具时就会 panic。正确做法是先判断len(choices) 0再看message.tool_calls是否为 nil。OAuth 相关报错。部分远程 MCP Server 需要 OAuth 认证stdio 本地服务一般不需要。如果你接的是 HTTP 传输的远程服务报 OAuth 错检查 Headers 里有没有带对 Authorization。本地 filesystem 和 git 工具走 stdio不会碰到这个。工具注册了但 LLM 不调用。这个不是报错但很常见。原因通常是工具描述太模糊或者 InputSchema 格式不对。检查适配器里parameters字段是不是从 MCP 的inputSchema正确转换过来的。另外工具名建议加前缀mcp_服务器名_工具名避免和本地工具重名。JSON-RPC id 不匹配。stdio 传输是异步的发请求和收响应通过 id 关联。如果 id 生成用了随机数但没做映射响应回来找不到对应请求就会超时。建议用自增 int64维护一个map[int64]chan Response做分发。排查顺序建议先确认模型侧 curl 能返回 tool_calls再确认 MCP Server 手动能启动最后看代码里的日志。三段日志哪段断了问题就在哪。6. 继续往下走从 MCP 到 Skill 的演进MCP 跑通后Agent 的工具生态就解耦了。新增工具只需要在 config.json 里加一个 Server 配置代码一行不用改。filesystem、git、数据库、内部 API只要有人写了符合 MCP 规范的 Server你的 Agent 就能即插即用。但工具多了会出新问题。想象一下几百个工具全塞进 Prompt上下文窗口瞬间被工具描述占满LLM 还会因为信息过载选错工具。这时候需要更高层的抽象把常用工具组合成 Skill让 Agent 按标准作业流程执行而不是每次临场发挥。下一篇会讲 Skill 的设计和实现把「代码评审」这种多步骤流程固化下来。当前这篇的完整代码可以先把 MCP 客户端和适配器部分抽出来作为独立模块复用。你可以在 TaoToken 的模型对话页面多试几个模型看看不同模型对 tool_calls 的支持程度选一个工具调用最稳的作为 Agent 默认模型。接入文档里有各模型的参数说明对照着调 temperature 和 max_tokens工具调用场景下 temperature 建议调低一点减少模型乱选工具的概率。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号