尧图精选

MCP 自动识别 AI 调用 vs 手动 callTool:两种场景的配置与验证

🕒 发布时间:2026/10/24 1:01:23 📁 来源:尧图网络
1. 先分清MCP 里到底谁在决定“调用工具”很多 Node 开发者第一次写 MCP Server 时会下意识觉得“工具注册完AI 就会自己用”。这个判断只对了一半。MCP 协议本身只负责把工具元数据暴露出去真正决定“要不要调用、调用哪个”的是上层客户端。客户端分两类行为完全不同。第一类是带 LLM 的可视化客户端比如 VS Code 里的 Copilot、Claude Desktop、Cursor。它们启动时会通过tools/list把 MCP Server 注册的所有工具名称、描述、inputSchema拉过去注入到模型上下文里。你在对话框里说“帮我生成一条随机用户写入 json”模型自己判断该用create-random-user然后客户端底层自动发tools/call。全程你一行callTool都不用写。第二类是你自己用modelcontextprotocol/sdk/client写的 Node 脚本、CLI 工具、自动化任务。这里没有大模型参与判断工具列表虽然也会同步但“要不要调用”完全由你的代码决定。你必须显式写mcp.callTool({ name, arguments })不写就永远不会触发。两种场景底层发给 MCP Server 的 JSON-RPC 报文一模一样都是{method:tools/call,params:{name:xxx,arguments:{}}}。差别只在触发主体一个是 LLM一个是你的代码逻辑。下面我把两种场景的配置骨架、TaoToken 通道接入、验证动作和排错都拆开讲你可以直接复制改。2. TaoToken 前置统一 Key 与 API 通道不管走哪种调用方式只要你的 MCP Server 内部需要反向调用大模型比如create-random-user里用 sampling 生成用户数据就得有一个稳定的模型通道。我习惯用 TaoToken 做统一入口一个 Key 覆盖对话和编码场景省得在多个平台之间来回切。官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后在控制台生成 API Key。API 基地址是 https://taotoken.net/api 注意这个地址不带任何查询参数配置时别自己拼 UTM。Key 的获取路径是控制台里的 API Keys 页面https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。生成后复制那串sk-开头的字符串后面settings.json和config.toml都要用。如果你只是想先验证模型通不通可以直接用模型对话页面发一条消息https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。能正常返回说明 Key 和通道没问题再往下配 MCP 就不会把“模型不通”和“MCP 配置错”混在一起排查。长期做编码和 Agent 的话Coding Plan 更划算入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 遇到参数疑问先翻这里。3. 可复制配置settings.json 与 config.toml 骨架3.1 场景一AI 客户端自动识别settings.jsonVS Code 系的 MCP 配置一般放在用户目录的settings.json或者项目里的.vscode/mcp.json。核心是告诉客户端“怎么启动这个 MCP Server”工具元数据由 Server 启动后自动上报你不需要在这里列工具。{ mcp: { servers: { random-user-server: { command: node, args: [/Users/you/projects/mcp-random-user/dist/index.js], env: { TAOTOKEN_API_KEY: sk-你的Key, TAOTOKEN_BASE_URL: https://taotoken.net/api } } } } }这里command是nodeargs指向你编译后的入口文件。env里把 TaoToken 的 Key 和基地址传进去Server 内部反向调模型时直接读环境变量。配好后重启客户端MCP Server 会以 stdio 方式被拉起握手阶段自动完成tools/list同步。3.2 场景二手动 callToolconfig.toml自建 Node CLI 或脚本场景我习惯用一个config.toml管理连接参数避免把 Key 硬编码进代码。Node 侧用iarna/toml或smol-toml解析都行。[mcp] server_command node server_args [./dist/index.js] transport stdio [taotoken] api_key sk-你的Key base_url https://taotoken.net/api model claude-3-5-sonnet [client] timeout_ms 30000transport目前 stdio 最省事进程内管道通信不用管端口。timeout_ms给 30 秒模型反向调用偶尔会慢太短会误判成失败。3.3 Server 侧工具注册两种场景共用不管哪种客户端Server 侧代码是一样的。用server.tool()注册名称、描述、inputSchema会被自动上报。import { McpServer } from modelcontextprotocol/sdk/server/mcp.js; import { StdioServerTransport } from modelcontextprotocol/sdk/server/stdio.js; import { z } from zod; const server new McpServer({ name: random-user-server, version: 1.0.0 }); server.tool( create-random-user, 生成一条随机用户数据并返回 JSON, { count: z.number().optional().default(1) }, async ({ count }) { const users Array.from({ length: count }, (_, i) ({ id: i 1, name: user_${Math.random().toString(36).slice(2, 8)}, email: u${Date.now()}${i}example.com })); return { content: [{ type: text, text: JSON.stringify(users, null, 2) }] }; } ); const transport new StdioServerTransport(); await server.connect(transport);inputSchema用 zod 描述客户端拿到后模型才知道count是可选数字。描述写清楚模型判断是否调用时全靠它。4. 验证请求与预期结果4.1 验证自动识别在 AI 客户端里发一句话配好settings.json后重启客户端在对话框输入“帮我生成 2 条随机用户写入 json”。预期链路是你的提问进入 LLM → 模型匹配到create-random-user→ 客户端底层自动发tools/call→ Server 执行 → 结果回到对话框。判断成功的标志是聊天框里直接出现两条用户 JSON且你没有写任何callTool代码。如果模型没调用工具先检查工具描述是否够明确再确认客户端是否真的加载了 MCP Server多数客户端有 MCP 状态面板。4.2 验证手动调用跑一段 Node 脚本自建场景写个最小脚本显式调用callToolimport { Client } from modelcontextprotocol/sdk/client/index.js; import { StdioClientTransport } from modelcontextprotocol/sdk/client/stdio.js; const transport new StdioClientTransport({ command: node, args: [./dist/index.js] }); const client new Client({ name: cli-client, version: 1.0.0 }, { capabilities: {} }); await client.connect(transport); const tools await client.listTools(); console.log(已同步工具:, tools.tools.map(t t.name)); const res await client.callTool({ name: create-random-user, arguments: { count: 2 } }); console.log(res.content[0].text);预期输出先打印已同步工具: [ create-random-user ]再打印两条用户 JSON。这里listTools是自动同步的但callTool必须你手写不写就没有任何调用发生。4.3 两种方式报文一致性验证想确认底层一致可以在 Server 的tools/call处理入口打日志。两种场景触发时你看到的params结构完全相同{method:tools/call,params:{name:create-random-user,arguments:{count:2}}}差别只在来源自动识别场景是客户端代发手动场景是你的脚本发。5. 本篇常见错排查报错一Tool not found: create-random-user。多数是 Server 没启动成功或者args路径写错。先在终端手动跑node ./dist/index.js能挂起不退出说明 Server 正常。如果报模块找不到检查是否执行过npm run build。报错二AI 客户端里模型不调用工具。先看工具描述是不是太模糊比如只写“生成用户”模型可能不确定。改成“生成一条随机用户数据并返回 JSON”这类明确动作。再确认客户端 MCP 面板里 Server 状态是绿色。报错三手动脚本connect超时。检查StdioClientTransport的command和args是否和config.toml一致。stdio 模式下 Server 不能往 stdout 打无关日志否则会污染 JSON-RPC 流。调试信息一律走console.error。报错四反向调模型返回 401。说明TAOTOKEN_API_KEY没传进 Server 进程。检查settings.json的env块或config.toml的api_key是否被正确读取。基地址确认是https://taotoken.net/api不要带多余路径。报错五inputSchema校验失败。zod 的.optional().default(1)在部分客户端里会被要求显式传参。如果模型不传count就报错把 default 逻辑挪到处理函数内部schema 只标 optional。6. 按场景选对入口别把两件事混着调自动识别和手动callTool是两条独立链路排错时一定要先确认自己处在哪条链路上。AI 客户端场景问题通常出在工具描述和客户端加载自建脚本场景问题通常出在传输配置和 Key 注入。把这两类分开排查效率会高很多。需要生成或管理 Key 时走 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 接入参数细节看 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。如果你在搭长期编码 AgentCoding Plan 入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。Claude Code 相关接入参考 https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。我自己的习惯是先用模型对话页面确认通道通再配 MCP Server最后分别用客户端和脚本各验证一次。这样任何一层出问题都能立刻定位不会在“到底是模型没识别还是代码没调用”之间反复猜。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →