ARTICLE DETAIL

资讯详情

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

三小时搞定AI工具开发:基于MCP的Node.js极简实践与TaoToken配置

三小时搞定AI工具开发:基于MCP的Node.js极简实践与TaoToken配置 1. 为什么我劝你先跑通 MCP 最小闭环而不是啃完协议文档MCP 全称 Model Context Protocol你可以把它理解成 AI 世界的 USB-C 接口标准模型不再需要为每个外部能力单独写死调用逻辑而是通过一套统一的 JSON-RPC 2.0 消息格式动态发现工具、发起调用、接收流式进度。Node.js 做 MCP 工具开发有天然优势——事件循环适合处理 SSE 长连接npm 生态里 express、eventsource 这些包拿来就能用三小时跑通一个可运行的最小实践完全够。这篇文章面向的是想快速验证工具调用链路的开发者你不需要先读完 MCP 规范全文也不用纠结 Function Calling 和 MCP 的哲学差异。我会带你从零搭一个 Node.js MCP 服务端注册一个真实可调用的工具再用 TaoToken 的统一 Key 把模型侧接进来最后用一次本地请求验证整条链路。全程可复制踩坑点我会标出来。适合谁有基础 Node.js 经验、想给 AI 应用加外部工具能力、但不想被各家模型 SDK 绑死的开发者。读完你能得到一个能跑的最小骨架后续往里面塞自己的业务工具就行。2. TaoToken 前置统一 Key 怎么拿、放哪里MCP 服务端本身不依赖任何模型厂商但你要验证模型调用工具这条链路就需要一个能访问模型的入口。TaoToken 在这里的角色是统一接入层一个 Key 覆盖多种模型省去你在 OpenAI、Anthropic 之间来回切 SDK 和鉴权配置的麻烦。操作路径很直接打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后在控制台生成 API Key。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite Key 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。API 基址统一用 https://taotoken.net/api 注意这个地址不带 UTM 参数直接写进配置即可。注意Key 只显示一次生成后立刻复制到本地环境变量或配置文件别提交到 Git。我习惯把 Key 放在项目根目录的.env里用dotenv加载。这样 MCP 服务端和客户端脚本都能读到同一个值不用硬编码。如果你用 Claude Code 这类工具它的配置走settings.json如果你用 Codex 风格的 CLI配置走config.toml。两种骨架我都会在下一节给出。3. 可复制配置settings.json 与 config.toml 骨架先给 Claude Code 风格的settings.json。这个文件一般放在项目根或用户配置目录核心是把 TaoToken 的基址和 Key 注入环境变量让后续的模型请求走统一入口{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的TaoTokenKey, MCP_SERVER_PORT: 3000 }, mcpServers: { local-tools: { command: node, args: [./server.js], env: { MCP_SERVER_PORT: 3000 } } } }再给 Codex 风格的config.toml字段名不同但思路一致[model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY [ mcp_servers.local_tools ] command node args [./server.js] env { MCP_SERVER_PORT 3000 }两个配置的共同点模型基址指向 TaoTokenMCP 服务端作为子进程启动。区别只是 JSON 和 TOML 的语法。你按自己用的工具选一个就行不用两个都配。接下来是服务端骨架server.js。我用 express 起 HTTP 服务实现 MCP 要求的两个核心端点发现端点和调用端点。工具注册用一个对象管理每个工具包含描述、参数 schema 和 handlerimport express from express; const app express(); app.use(express.json()); const tools { get_time: { description: 获取当前服务器时间返回 ISO 格式字符串, parameters: { type: object, properties: { timezone: { type: string, description: 时区如 Asia/Shanghai } }, required: [] }, handler: async ({ timezone Asia/Shanghai }) { const now new Date().toLocaleString(zh-CN, { timeZone: timezone }); return { time: now, timezone }; } } }; app.post(/mcp/discover, (req, res) { res.json({ jsonrpc: 2.0, result: { protocol_version: 1.0, tools: Object.entries(tools).map(([name, def]) ({ name, description: def.description, parameters: def.parameters })) }, id: req.body.id || null }); }); app.post(/mcp/invoke, async (req, res) { const { jsonrpc, method, params, id } req.body; if (jsonrpc ! 2.0) { return res.status(400).json({ jsonrpc: 2.0, error: { code: -32600, message: Invalid Request }, id }); } const [, toolName] method.split(.); const tool tools[toolName]; if (!tool) { return res.json({ jsonrpc: 2.0, error: { code: -32601, message: Method not found }, id }); } try { const result await tool.handler(params || {}); res.json({ jsonrpc: 2.0, result, id }); } catch (err) { res.json({ jsonrpc: 2.0, error: { code: -32603, message: err.message }, id }); } }); app.listen(process.env.MCP_SERVER_PORT || 3000, () { console.log(MCP server on http://localhost:${process.env.MCP_SERVER_PORT || 3000}); });这段代码的关键点/mcp/discover返回工具清单模型侧据此生成可调用的函数描述/mcp/invoke按 JSON-RPC 2.0 格式处理调用method 用tool.工具名的约定解析。错误码沿用 JSON-RPC 标准-32600 是请求非法-32601 是方法不存在-32603 是内部错误。4. 验证请求从发现工具到拿到结果服务端跑起来后先验证发现端点。启动服务node server.js另开一个终端用 curl 发发现请求curl -X POST http://localhost:3000/mcp/discover \ -H Content-Type: application/json \ -d {jsonrpc:2.0,method:discover,id:1}预期返回{ jsonrpc: 2.0, result: { protocol_version: 1.0, tools: [ { name: get_time, description: 获取当前服务器时间返回 ISO 格式字符串, parameters: { type: object, properties: { timezone: { type: string, description: 时区如 Asia/Shanghai } }, required: [] } } ] }, id: 1 }看到这个说明工具注册成功。接着验证调用端点curl -X POST http://localhost:3000/mcp/invoke \ -H Content-Type: application/json \ -d {jsonrpc:2.0,method:tool.get_time,params:{timezone:Asia/Shanghai},id:2}预期返回类似{ jsonrpc: 2.0, result: { time: 2025/1/15 14:30:00, timezone: Asia/Shanghai }, id: 2 }到这里MCP 服务端的工具注册与调用链路已经通了。接下来把模型侧接进来用 TaoToken 的 Key 发起一次对话让模型决定是否调用get_time。客户端脚本核心逻辑是先从/mcp/discover拉工具列表转成模型能识别的函数描述再把模型返回的工具调用请求转发到/mcp/invokeconst API_BASE https://taotoken.net/api; const API_KEY process.env.TAOTOKEN_API_KEY; async function getMCPTools() { const res await fetch(http://localhost:3000/mcp/discover, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ jsonrpc: 2.0, method: discover, id: 1 }) }); const { result } await res.json(); return result.tools.map(t ({ type: function, function: { name: tool.${t.name}, description: t.description, parameters: t.parameters } })); } async function callMCPTool(method, params) { const res await fetch(http://localhost:3000/mcp/invoke, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ jsonrpc: 2.0, method, params, id: Date.now() }) }); return (await res.json()).result; } async function main() { const tools await getMCPTools(); const chatRes await fetch(${API_BASE}/v1/messages, { method: POST, headers: { Content-Type: application/json, x-api-key: API_KEY, anthropic-version: 2023-06-01 }, body: JSON.stringify({ model: claude-3-5-sonnet-20241022, max_tokens: 1024, messages: [{ role: user, content: 现在几点了 }], tools }) }); const data await chatRes.json(); const toolUse data.content?.find(c c.type tool_use); if (toolUse) { const result await callMCPTool(toolUse.name, toolUse.input); console.log(工具返回, result); } else { console.log(模型直接回答, data.content); } } main();跑通后你会看到控制台打印出工具返回的时间对象。这一步成功说明模型 → MCP 发现 → 工具调用 → 结果回传整条链路是通的。想更直观地验证模型对话效果可以到 https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 手动发几条消息对比。5. 本篇常见错排查报错一ECONNREFUSED 127.0.0.1:3000服务端没启动或者端口被占用。先确认node server.js在跑再用lsof -i :3000看端口占用。改端口就改MCP_SERVER_PORT环境变量客户端里的地址同步改。报错二Invalid Request且 code 为 -32600请求体里jsonrpc字段不是字符串2.0或者 JSON 格式本身有语法错误。用 curl 时注意单引号包裹Windows 的 cmd 对单引号支持不好建议用 PowerShell 或 Git Bash。报错三Method not found且 code 为 -32601method 格式写错了。约定是tool.工具名比如tool.get_time。如果你注册的工具名带下划线别写成驼峰。另外检查/mcp/discover返回的 tools 数组里确实有这个工具。报错四模型侧返回 401 或鉴权失败TaoToken 的 Key 没读到或者 header 名写错。Anthropic 风格用x-api-keyOpenAI 风格用Authorization: Bearer。确认.env已加载process.env.TAOTOKEN_API_KEY有值。基址确认是https://taotoken.net/api不要多加/v1之外的路径。报错五工具 handler 抛异常但客户端只看到 -32603这是服务端 catch 后统一返回的内部错误。调试时在 handler 里加console.error(err)看服务端终端的堆栈。常见原因是参数类型不匹配比如 timezone 传了数字。报错六SSE 流式端点连不上如果你扩展了流式端点注意Content-Type必须是text/event-stream且每条消息以\n\n结尾。用浏览器直接访问会一直挂起这是正常的用 curl 加-N参数看输出。6. 下一步把工具换成你自己的业务逻辑最小闭环跑通后扩展方式很直接在tools对象里加新条目写好 description 和 parameters schemahandler 里接你的数据库、内部 API 或计算逻辑。模型侧不用改任何代码/mcp/discover会自动把新工具暴露出去。如果你要长期做编码类 Agent建议把 MCP 服务端和模型调用分开部署服务端常驻客户端按需拉起。TaoToken 的 Coding Plan 适合这种长期编码场景地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有各语言 SDK 的基址配置示例。我实测下来最容易卡住的地方不是协议本身而是配置文件的字段名和 header 名对不上。把第 3 节的settings.json或config.toml直接复制过去改 Key 就能跑省掉大量试错时间。工具 handler 里记得加超时控制外部 API 慢的时候别把整个 MCP 服务端拖死。
返回列表