news 2026/10/7 7:10:27

借助智能体编写高效的智能体工具:用 Claude Code 与 MCP 打造可复用工具链的 TaoToken 实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
借助智能体编写高效的智能体工具:用 Claude Code 与 MCP 打造可复用工具链的 TaoToken 实践

1. 当 Claude Code 开始给自己造工具:一个真实项目的起点

你可能已经用 Claude Code 写过业务代码,但有没有想过让它给自己造工具?我最近在做一个内部数据查询系统时,遇到了一个典型场景:团队需要频繁查询订单状态、用户信息和日志摘要,每次都要手动写 SQL 或者翻日志文件。最初的做法是给 Claude Code 一个长长的系统提示,把所有查询逻辑都塞进去,结果上下文很快就被撑爆,而且每次调用都要重新解释一遍表结构。

后来我换了个思路:让 Claude Code 自己生成 MCP 工具,把这些查询逻辑封装成独立的工具函数,注册到 MCP 服务器上,然后 Claude Code 通过工具调用来完成任务。这样上下文里只需要保留工具的描述和参数定义,具体的查询逻辑都在工具内部执行,Token 消耗直接降了三分之二。

这个思路的核心就是「用智能体写智能体工具」——Claude Code 作为编码智能体,MCP 作为工具协议,两者结合形成一个可复用的工具链。你不需要手动写每一个工具的实现,而是让 Claude Code 根据你的需求生成工具代码、调试、注册,最后沉淀成一套可以反复使用的工具集。

这篇文章会带你走完整个流程:从环境准备到工具生成,从 MCP 配置到端到端验证。每一步都有可复制的配置片段和命令,你可以直接跟着操作。适合已经用过 Claude Code 或者 Cline 这类编码智能体、想进一步把工具链落到真实项目的开发者。如果你还没接触过 MCP,也不用担心,我会从最基础的概念讲起。

2. 前置准备:TaoToken 接入与 Claude Code 环境配置

在开始写工具之前,你需要先确保 Claude Code 能正常调用模型。这里我用 TaoToken 作为 API 接入层,它兼容 Anthropic 的接口格式,配置起来比较直接。如果你已经有其他接入方式,也可以跳过这部分,只要保证 Claude Code 能正常发请求就行。

首先去 TaoToken 官网注册账号,然后在控制台创建一个 API Key。地址是 https://taotoken.net/api-keys,创建的时候注意选择对应的权限范围,一般选默认的读写权限就够了。创建完成后把 Key 复制下来,后面配置会用到。

接下来配置 Claude Code 的环境变量。Claude Code 默认会读取ANTHROPIC_API_KEY和ANTHROPIC_BASE_URL这两个变量。你可以在终端里直接 export,也可以写进 shell 配置文件里持久化。我习惯用.env文件管理,这样切换环境方便。

# 在项目根目录创建 .env 文件 cat > .env << 'EOF' ANTHROPIC_API_KEY=sk-your-taotoken-key-here ANTHROPIC_BASE_URL=https://taotoken.net/api EOF # 加载环境变量 source .env

如果你用的是 Claude Code 的 CLI 版本,还需要确认一下版本号。我实测下来 0.8.x 以上的版本对 MCP 的支持比较完整。可以用claude --version查看,如果版本太低就升级一下。

# 查看当前版本 claude --version # 如果低于 0.8.0,用 npm 升级 npm install -g @anthropic-ai/claude-code@latest

配置完成后,先跑一个简单的请求验证一下连通性。不需要写代码,直接在终端里用 curl 测试:

curl -X POST https://taotoken.net/api/v1/messages \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{ "model": "claude-sonnet-4-20250514", "max_tokens": 100, "messages": [{"role": "user", "content": "回复 OK 两个字母"}] }'

如果返回的 JSON 里有content字段且包含 "OK",说明接入正常。这一步很重要,因为后面 MCP 工具调用会频繁发请求,如果基础接入有问题,排查起来会很麻烦。

关于模型选择,Claude Code 默认用的是 Sonnet 系列,你也可以在配置里指定其他模型。TaoToken 支持多个模型 ID,具体可以在模型对话页面查看:https://taotoken.net/models。我一般用claude-sonnet-4-20250514做工具生成,速度快且代码质量稳定。

还有一个容易忽略的点:Claude Code 需要访问文件系统来读写工具代码。确保你的工作目录有足够的权限,并且不要在只读文件系统里运行。如果你在容器里开发,记得把工作目录挂载进去。

3. 可复制的 MCP 工具配置:从零生成一个订单查询工具

现在进入核心部分:让 Claude Code 生成一个 MCP 工具。我会用一个订单查询的场景来演示,工具的功能是「根据订单号查询订单状态和金额」。这个工具会封装数据库查询逻辑,Claude Code 只需要传入订单号就能拿到结果。

首先创建项目结构。我习惯把 MCP 服务器和工具代码分开存放,这样后续扩展方便:

mkdir -p mcp-order-tools/src/tools cd mcp-order-tools npm init -y npm install @modelcontextprotocol/sdk zod npm install -D typescript @types/node tsx

然后创建 TypeScript 配置:

{ "compilerOptions": { "target": "ES2022", "module": "Node16", "moduleResolution": "Node16", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true }, "include": ["src/**/*"] }

接下来是关键步骤:让 Claude Code 生成工具代码。你可以直接在 Claude Code 的对话里描述需求,比如:

帮我写一个 MCP 工具,名字叫 query_order,接收一个 order_id 参数,返回订单的状态、金额和创建时间。用 zod 做参数校验,返回格式用 JSON。

Claude Code 会生成类似下面的代码。我把它保存到src/tools/query-order.ts:

import { z } from "zod"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; // 模拟数据库查询,实际项目中替换为真实查询 async function fetchOrderFromDB(orderId: string) { // 这里用模拟数据演示,真实场景接数据库 const mockOrders: Record<string, any> = { "ORD-2024-001": { order_id: "ORD-2024-001", status: "shipped", amount: 299.00, currency: "CNY", created_at: "2024-11-01T10:23:00Z", }, "ORD-2024-002": { order_id: "ORD-2024-002", status: "pending", amount: 158.50, currency: "CNY", created_at: "2024-11-03T14:05:00Z", }, }; return mockOrders[orderId] || null; } export function registerQueryOrderTool(server: McpServer) { server.tool( "query_order", "根据订单号查询订单的详细状态,包括状态、金额和创建时间", { order_id: z.string().describe("订单号,格式如 ORD-2024-001"), }, async ({ order_id }) => { const order = await fetchOrderFromDB(order_id); if (!order) { return { content: [ { type: "text", text: JSON.stringify({ error: "ORDER_NOT_FOUND", message: `未找到订单 ${order_id},请检查订单号是否正确`, }), }, ], }; } return { content: [ { type: "text", text: JSON.stringify(order), }, ], }; } ); }

这段代码有几个设计点值得注意。第一,工具描述写得很具体,明确说了「根据订单号查询订单的详细状态」,这样 Claude Code 在决定是否调用这个工具时能准确判断。第二,参数用 zod 做了类型校验,并且describe里给了格式示例,减少传错参数的概率。第三,错误返回不是简单的「not found」,而是带了错误码和可操作的提示信息,这样 Claude Code 看到后能自己调整策略。

然后创建 MCP 服务器的入口文件src/server.ts:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { registerQueryOrderTool } from "./tools/query-order.js"; const server = new McpServer({ name: "order-tools", version: "1.0.0", }); // 注册所有工具 registerQueryOrderTool(server); // 启动服务器 const transport = new StdioServerTransport(); await server.connect(transport); console.error("Order MCP server running on stdio");

注意这里用的是console.error而不是console.log,因为 stdio 传输模式下 stdout 会被 MCP 协议占用,日志必须走 stderr,否则会干扰协议通信。这个坑我踩过,当时调试了半天才发现是日志输出位置的问题。

接下来配置 Claude Code 连接这个 MCP 服务器。在项目根目录创建.mcp.json:

{ "mcpServers": { "order-tools": { "command": "npx", "args": ["tsx", "src/server.ts"], "env": { "NODE_ENV": "development" } } } }

如果你想让 Claude Code 全局都能用这个工具,可以把配置写到~/.claude/mcp.json里。项目级的配置只在当前目录生效,适合团队协作时共享。

配置完成后,用 Claude Code 的 CLI 命令验证一下 MCP 服务器是否能正常启动:

claude mcp list

如果看到order-tools在列表里且状态是 connected,说明配置成功。如果显示 failed,可以用claude mcp logs order-tools查看具体错误。

4. 端到端验证:生成工具→注册→调用→回读结果

配置写好了,但工具到底能不能用?这一节我们走一遍完整的验证流程,确保每个环节都通。

第一步,确认 MCP 服务器能独立启动。在终端里直接运行:

npx tsx src/server.ts

如果看到 stderr 输出Order MCP server running on stdio,说明服务器启动正常。按 Ctrl+C 退出,然后进入下一步。

第二步,在 Claude Code 里发起一个需要调用工具的请求。打开 Claude Code 的交互界面,输入:

帮我查一下订单 ORD-2024-001 的状态

Claude Code 应该会自动识别出需要调用query_order工具,并传入order_id: "ORD-2024-001"。你会在界面上看到工具调用的过程,包括请求参数和返回结果。

如果一切正常,返回结果应该是:

{ "order_id": "ORD-2024-001", "status": "shipped", "amount": 299.00, "currency": "CNY", "created_at": "2024-11-01T10:23:00Z" }

第三步,测试错误场景。输入一个不存在的订单号:

查一下订单 ORD-9999-999

Claude Code 调用工具后会收到错误响应,然后它应该能根据错误信息告诉你「未找到该订单,请检查订单号」。这说明工具的错误处理逻辑生效了,而且 Claude Code 能正确解读错误响应。

第四步,回读结果并验证。让 Claude Code 把查询结果整理成表格:

把刚才两个订单的查询结果整理成表格,包含订单号、状态、金额三列

Claude Code 会基于之前的工具调用结果生成表格。这一步验证的是「工具返回的上下文是否足够支撑后续推理」。如果工具返回的信息太简略,Claude Code 就没法完成这个任务;如果返回了太多无关字段,又会浪费上下文。

整个流程跑通后,你可以把工具代码提交到 Git 仓库,团队成员拉取后只需要配置自己的 API Key 就能使用同一套工具。这就是「可复用工具链」的价值——工具逻辑只写一次,所有人共享。

如果你想让工具更健壮,可以加一个简单的评估脚本。比如写一个eval.ts,批量测试多个订单号的查询结果是否符合预期:

import { fetchOrderFromDB } from "./tools/query-order.js"; const testCases = [ { input: "ORD-2024-001", expectedStatus: "shipped" }, { input: "ORD-2024-002", expectedStatus: "pending" }, { input: "ORD-9999-999", expectedStatus: null }, ]; async function runEval() { let passed = 0; for (const tc of testCases) { const result = await fetchOrderFromDB(tc.input); const actualStatus = result ? result.status : null; if (actualStatus === tc.expectedStatus) { passed++; console.log(`PASS: ${tc.input}`); } else { console.log(`FAIL: ${tc.input}, expected ${tc.expectedStatus}, got ${actualStatus}`); } } console.log(`\n${passed}/${testCases.length} passed`); } runEval();

这个评估脚本虽然简单,但能帮你在修改工具逻辑后快速回归测试。Claude Code 也可以帮你扩展这个脚本,比如加入更多边界用例、自动生成测试数据等。

5. 常见报错排查:401、local proxy failed 与 reading choices

即使配置看起来没问题,实际运行时还是可能遇到各种报错。这一节整理几个我实际遇到过的错误和排查方法。

401 Unauthorized

这是最常见的错误,通常是 API Key 配置有问题。先检查.env文件里的ANTHROPIC_API_KEY是否以sk-开头,有没有多余的空格或换行。然后确认ANTHROPIC_BASE_URL设置的是https://taotoken.net/api,不要在后面加/v1或者斜杠。

如果 Key 确认没问题,用 curl 单独测试一下:

curl -X POST https://taotoken.net/api/v1/messages \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{"model":"claude-sonnet-4-20250514","max_tokens":10,"messages":[{"role":"user","content":"hi"}]}'

如果 curl 也返回 401,说明 Key 本身有问题,去 TaoToken 控制台重新生成一个。如果 curl 正常但 Claude Code 报 401,检查 Claude Code 是否读取了正确的环境变量——有时候 shell 里 export 了但 Claude Code 进程没继承到。

local proxy failed / connection refused

这个错误通常出现在 MCP 服务器启动失败时。Claude Code 尝试连接本地 MCP 进程但连不上。排查步骤:

先手动运行 MCP 服务器命令,看是否有报错:

npx tsx src/server.ts

如果提示模块找不到,检查package.json里的依赖是否安装完整,运行npm install重新安装。如果是 TypeScript 编译错误,用npx tsc --noEmit单独检查。

另一个常见原因是路径问题。.mcp.json里的args路径是相对于项目根目录的,如果你在子目录里启动 Claude Code,路径就会不对。建议用绝对路径或者确认工作目录正确。

reading choices 相关错误

这个错误一般出现在模型返回格式不符合预期时。比如工具返回的内容不是合法的 JSON,或者返回了空内容。检查工具代码里的返回逻辑,确保content数组里至少有一个type: "text"的元素,且text字段是字符串。

如果你在工具里做了异步操作但忘记 await,也可能导致返回 undefined。用 TypeScript 的严格模式能提前发现这类问题。

OAuth 相关报错

如果你看到 OAuth 相关的错误,通常是因为 Claude Code 尝试用 OAuth 流程认证但配置不支持。在.env里显式设置ANTHROPIC_API_KEY后,Claude Code 会优先用 Key 认证,不会再走 OAuth。如果还是报错,检查是否有其他环境变量干扰,比如CLAUDE_CODE_USE_OAUTH之类的设置。

工具调用成功但结果不对

这种情况一般是工具逻辑本身的问题。建议在工具函数里加日志,输出实际查询的参数和返回的数据。因为 stdio 模式下 stdout 被占用,日志要写到 stderr 或者文件里:

import { appendFileSync } from "fs"; function logDebug(msg: string) { appendFileSync("/tmp/mcp-debug.log", `${new Date().toISOString()} ${msg}\n`); }

然后在工具函数的关键节点调用logDebug,运行后查看/tmp/mcp-debug.log就能定位问题。

排查完这些常见错误后,你的工具链应该能稳定运行了。如果遇到其他报错,可以去 TaoToken 的接入文档页面看看有没有相关说明:https://taotoken.net/doc。

6. 把工具链沉淀下来:从单次使用到长期复用

工具跑通之后,下一步是让它真正成为团队的基础设施。我自己的做法是建一个独立的 Git 仓库专门存放 MCP 工具,每个工具一个目录,配好 README 和评估脚本。新项目需要什么工具,直接从仓库里引入对应的 MCP 服务器配置就行。

具体来说,我会在仓库根目录放一个tools-registry.json,记录所有可用工具的元信息:

{ "tools": [ { "name": "order-tools", "description": "订单查询相关工具", "path": "./mcp-order-tools", "command": "npx tsx src/server.ts", "tools": ["query_order"] }, { "name": "log-tools", "description": "日志检索工具", "path": "./mcp-log-tools", "command": "npx tsx src/server.ts", "tools": ["search_logs", "get_log_context"] } ] }

然后在项目里写一个脚本,根据这个 registry 自动生成.mcp.json。这样新增工具时只需要更新 registry,不用手动改每个项目的配置。

对于长期编码和 Agent 场景,可以考虑用 Coding Plan 来管理工具链的调用配额和权限。地址是 https://taotoken.net/coding-plan,适合需要频繁调用工具、对稳定性要求高的团队。

另外,Claude Code 本身也支持通过claude mcp add命令动态添加 MCP 服务器。如果你不想手动编辑 JSON 文件,可以用命令行:

claude mcp add order-tools npx tsx /path/to/mcp-order-tools/src/server.ts

这个命令会把配置写到全局的~/.claude/mcp.json里,所有项目都能用。删除的话用claude mcp remove order-tools。

最后分享一个实用技巧:把常用的工具调用组合成「工作流」。比如「查订单→查日志→生成报告」这个流程,可以在 Claude Code 里用一条指令触发,它会自动按顺序调用多个工具。你只需要在系统提示里描述清楚工作流的步骤,Claude Code 就能自己编排工具调用顺序。这样即使工具数量增长到几十个,你也不用记住每个工具的用法,只需要描述目标,让 Claude Code 自己决定调哪些工具。

工具链的价值不在于工具本身有多复杂,而在于它能不能让智能体更高效地完成任务。我试过把同一个查询逻辑分别做成「一个大工具」和「三个小工具」,结果发现小工具的组合方式更灵活,Claude Code 在不同场景下能选择不同的调用路径,整体成功率反而更高。所以设计工具时不用追求「一步到位」,先做最小可用的版本,然后在实际使用中根据评估结果迭代,这样沉淀下来的工具链才真正好用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 7:07:54

Cursor 显示所在区域无法打开?把 Base URL 改到 TaoToken 的排查思路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华