news 2026/5/2 12:04:38

基于MCP协议构建AI助手工具箱:从原理到实战部署

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于MCP协议构建AI助手工具箱:从原理到实战部署

1. 项目概述:一个为AI助手打造的工具箱

如果你正在使用Claude Code、Cursor或者Windsurf这类“AI原生”的编辑器,并且已经厌倦了每次都要手动复制文件路径、查询数据库或者调用特定API,那么你很可能已经听说过MCP(Model Context Protocol)。简单来说,MCP就是一个让AI助手能够安全、可控地使用外部工具和数据的协议。而lordbasilaiassistant-sudo/mcp-starter-kit这个项目,就是一个为你快速搭建自己MCP服务器的“脚手架”或“样板间”。

想象一下,你是一个开发者,每天要处理大量重复性的上下文查询:比如“帮我看看/src/utils目录下有哪些文件”、“查询一下用户表里最近一周的活跃用户”、“调用GitHub API获取我仓库的issue列表”。每次都需要你手动操作,然后复制结果给AI。MCP服务器的存在,就是让AI助手能自己安全地去做这些事。这个Starter Kit的价值在于,它不是一个空壳子,而是一个生产就绪的模板,内置了5个核心模块、10个开箱即用的工具,覆盖了文件操作、网络请求、数据库查询、API调用和基础计算等高频场景。它用TypeScript和Zod构建,提供了清晰的模块化架构、完善的错误处理和测试套件,让你能在几分钟内,而不是几小时内,就拥有一个专属于你工作流的、功能强大的AI助手工具箱。

2. 核心架构与设计思路拆解

2.1 为什么选择MCP与Starter Kit?

MCP协议的核心优势在于其简洁与安全。它不像传统的插件系统需要复杂的HTTP API和认证,而是通过标准输入输出(stdio)进行JSON-RPC通信。这意味着你的服务器作为一个子进程运行,生命周期完全由AI客户端管理,无需担心端口冲突、网络防火墙或API密钥泄露到模型上下文中。对于开发者而言,这种设计极大地降低了开发和集成的复杂度。

这个Starter Kit的设计哲学是“开箱即用,易于扩展”。它没有让你从零开始去理解MCP SDK的每一个细节,而是通过一组精心设计的范例工具,展示了五种最常用的开发模式。当你需要添加自己的工具时,几乎就是“填空”的过程:复制一个工具文件模板,修改工具名、描述、参数定义和核心逻辑,然后在入口文件注册一下即可。这种设计极大地降低了认知负担,让你能快速聚焦于业务逻辑本身,而不是协议细节。

2.2 模块化架构的深层考量

项目采用了一种清晰的水平分层与垂直模块化结合的结构。

  • 水平分层src/types.ts提供了success()failure()这两个核心响应助手函数,确保了所有工具返回给AI的数据格式是统一、结构化的。这不仅仅是代码复用,更是为了提升AI的可读性。一个结构化的错误响应能让Claude更好地理解问题所在并给出建议。
  • 垂直模块化:每个工具模块(如calculator.ts,file-manager.ts)都是独立的。这种设计带来了几个好处:
    1. 可插拔性:如果你不需要数据库功能,完全可以不安装better-sqlite3依赖,甚至删除database-query.ts文件,服务器其他部分照常运行。
    2. 关注点分离:每个文件只处理一类问题,代码更清晰,便于维护和测试。
    3. 易于学习:你可以逐个模块研究,理解不同的模式,比如同步计算、异步I/O、安全沙箱等。

2.3 安全性设计:从协议到实现

安全性是MCP服务器的生命线。Starter Kit在多个层面内置了防护措施:

  1. 协议层安全:MCP本身是单向的,客户端发起请求,服务器响应。服务器无法主动向客户端推送信息或执行操作,这构成了第一道屏障。
  2. 输入验证层:所有工具参数都使用Zod库进行模式验证和类型转换。这不仅能防止无效数据进入处理流程,其.describe()方法生成的描述还会直接被AI阅读,作为其决定是否及如何调用工具的依据。例如,一个标记为z.string().url()的参数,AI会自然地尝试输入一个合法的URL。
  3. 资源访问控制
    • 文件系统:通过FILE_ROOT环境变量,严格限制了文件管理器工具可以访问的根目录,有效防止路径遍历攻击(如../../../etc/passwd)。
    • 数据库:使用参数化查询(prepared statements)来杜绝SQL注入风险。better-sqlite3库原生支持这种方式,将用户输入的数据与SQL指令分离。
    • 网络请求:Web Fetcher工具支持配置超时(AbortSignal)和响应大小限制,防止恶意URL或过大响应导致服务器资源耗尽。
  4. 错误处理范式:强制使用failure()函数返回错误,而不是直接throw。这保证了即使发生异常,返回给AI的也是一个结构化的、包含错误信息和修复提示的JSON对象,避免了进程崩溃和不可读的错误堆栈信息泄露给终端用户。

3. 工具模块深度解析与实操要点

3.1 文件管理器:安全与便利的平衡

文件管理器模块(file-manager.ts)可能是最常用也最需要谨慎对待的工具。它提供了read_file,write_file,list_files三个功能。

注意FILE_ROOT的配置至关重要。在开发环境,你可以设置为项目根目录;在生产环境,务必将其设置为一个专用的、仅包含必要数据的目录,绝对不要设置为/或用户家目录。

list_files工具的递归陷阱与防护:该工具支持递归列出子目录,但Starter Kit通过代码逻辑隐式地防止了无限递归和性能问题。在实际扩展时,如果你需要处理超深目录树,强烈建议添加一个maxDepth参数并在实现中做硬性限制,避免因符号链接或循环目录导致递归爆炸。

read_file的智能响应:工具内实现了简单的JSON检测。如果文件内容看起来是JSON,它会尝试解析并以格式化的漂亮打印(pretty-print)形式返回,这极大提升了AI阅读代码或配置文件的可读性。这个细节体现了为AI优化输出,而不仅仅是完成功能。

实操心得:在处理文件写入时,工具会自动创建不存在的父目录(fs.mkdirSyncrecursive: true选项)。这是一个非常贴心的设计,避免了因目录不存在导致的写入失败。但这也意味着,你需要确保FILE_ROOT下的目录结构是你可以控制的。

3.2 数据库查询:SQLite的轻量级集成

数据库模块(database-query.ts)巧妙地使用了better-sqlite3这个可选依赖。它展示了如何优雅地处理可选功能

依赖的优雅降级:在package.json中,better-sqlite3被列为optionalDependencies。在工具注册函数内部,会检查该模块是否成功导入。如果导入失败(即用户未安装),注册工具的函数会直接返回,并且这些数据库工具根本不会出现在AI客户端的工具列表中。同时,在db_query等工具的实现里,也有相应的检查,如果模块缺失,会返回一个友好的failure()提示用户安装。这样,服务器主体功能完全不受影响。

读写分离的设计:工具区分了db_query(只读SELECT)和db_execute(写操作)。这不仅是语义上的清晰,更为未来实现更细粒度的权限控制(比如基于环境变量或令牌的只读模式)留下了扩展点。

参数化查询的必须性:所有接受用户输入拼接SQL的地方,都严格使用了?占位符和参数数组。这是防止SQL注入的黄金法则。Starter Kit的代码做了很好的示范:

const stmt = db.prepare(`SELECT * FROM ${tableName} LIMIT ?`); const results = stmt.all([limit]); // 安全:limit 被参数化

请注意,表名tableName这里是通过db_list_tables得到的,是可信列表中的值,而非直接用户输入。如果必须让用户输入表名,则需要一个额外的白名单校验步骤。

3.3 API调用器:配置化与集中管理

API调用器模块(api-caller.ts)实现了一个注册表模式。你不需要在每次AI调用时都让AI记住完整的URL、请求方法和认证头。相反,你在环境变量API_CONFIG中预定义一组API端点(如“github”、“jira”、“internal-api”),每个端点包含基地址、默认头等信息。

模式优势

  1. 安全性:敏感的API密钥只存储在环境变量或本地配置中,永远不会暴露给AI的对话上下文。
  2. 便利性:AI只需知道“调用github API获取issue”,工具内部会补全完整的URL和认证头。
  3. 可维护性:API配置集中在一处,如需更换密钥或基地址,只需修改配置,无需改动代码或重新教育AI。

配置示例深度解析

{ "name": "github", "base_url": "https://api.github.com", "headers": { "Authorization": "Bearer ghp_xxxx", "Accept": "application/vnd.github.v3+json" }, "default_timeout": 10000 }

这里的headers是静态的。如果你的认证需要动态令牌(如OAuth 2.0),可以在工具处理函数中引入更复杂的逻辑,例如从安全的存储中获取刷新令牌。default_timeout是一个很好的实践,避免了网络悬挂请求。

3.4 Web Fetcher:通用HTTP客户端的实现

Web Fetcher工具(fetch_url)是一个通用的HTTP客户端,它演示了如何处理异步操作、超时和响应处理。

超时控制:使用AbortSignalsetTimeout是实现请求超时的标准且优雅的方式。Starter Kit中,如果响应时间超过设定值,请求会被中止,并返回一个清晰的超时错误。这对于调用不可控的外部服务至关重要。

响应处理策略:工具会尝试将响应文本解析为JSON,如果失败则返回原始文本。同时,它引入了一个响应截断机制:如果响应体过大(比如一个巨大的HTML页面),会只返回前面一部分并附加提示。这是防止大响应体撑爆AI上下文窗口(context window)的实用技巧,因为AI客户端的上下文长度是有限的。

实操心得:在扩展此工具时,可以考虑增加对更多HTTP方法的支持(如PATCH),或者添加对请求体为multipart/form-data的处理能力,以便上传文件。同时,对于重定向的处理策略(fetchredirect选项)也应根据实际需求进行配置。

4. 从零开始构建与扩展自定义工具

4.1 创建工具的完整流程与最佳实践

假设我们要添加一个“天气查询”工具。以下是步步为营的实操指南:

第一步:规划工具定义在动手写代码前,先想清楚:

  • 工具名get_weather(使用蛇形命名,清晰易懂)。
  • 描述:这是AI选择工具的关键。要具体,如“根据城市名称查询当前天气状况和温度,数据来源于公开天气API。”
  • 参数city(城市名,字符串,必需)。未来可扩展units(单位制,枚举:metric/imperial)。
  • 返回值:结构化的JSON,包含城市、天气描述、温度、体感温度、湿度等。

第二步:实现工具模块创建src/tools/weather.ts

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import { success, failure } from "../types.js"; // 假设我们使用一个假想的天气API const WEATHER_API_KEY = process.env.WEATHER_API_KEY; const WEATHER_API_BASE = "https://api.weatherapi.com/v1"; export function registerWeatherTools(server: McpServer): void { server.tool( "get_weather", "根据城市名称查询当前天气状况、温度和湿度。数据来源于WeatherAPI。", { city: z.string().min(1).describe("要查询天气的城市名称,例如:Beijing, London, New York"), // 未来可扩展参数示例: // units: z.enum(["metric", "imperial"]).optional().default("metric").describe("温度单位,metric为摄氏度,imperial为华氏度"), }, async ({ city }) => { // 1. 参数校验与预处理 if (!WEATHER_API_KEY) { return failure( "Weather API key is not configured.", "请设置 WEATHER_API_KEY 环境变量。" ); } try { // 2. 构造请求(注意:示例URL,实际需查阅对应API文档) const url = new URL(`${WEATHER_API_BASE}/current.json`); url.searchParams.append("key", WEATHER_API_KEY); url.searchParams.append("q", city); url.searchParams.append("aqi", "no"); // 不查询空气质量 const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 10000); // 10秒超时 // 3. 执行网络请求 const response = await fetch(url.toString(), { signal: controller.signal, }); clearTimeout(timeoutId); if (!response.ok) { // 处理API返回的错误,如城市未找到 const errorBody = await response.text(); return failure( `Weather API request failed with status ${response.status}`, `API响应: ${errorBody}. 请检查城市名称是否正确。` ); } // 4. 解析并格式化响应 const data = await response.json(); const { location, current } = data; // 5. 返回结构化的成功结果 return success({ location: `${location.name}, ${location.country}`, condition: current.condition.text, temperature_c: current.temp_c, temperature_f: current.temp_f, feelslike_c: current.feelslike_c, humidity: current.humidity, wind_kph: current.wind_kph, last_updated: current.last_updated, }); } catch (err) { // 6. 统一的错误处理 if (err.name === 'AbortError') { return failure("请求超时。", "网络较慢或天气服务无响应,请稍后重试。"); } return failure( `查询天气时发生意外错误: ${err instanceof Error ? err.message : String(err)}`, "请检查网络连接或服务配置。" ); } } ); }

第三步:注册工具src/index.ts中导入并注册:

// ... 其他导入 import { registerWeatherTools } from "./tools/weather.js"; // 在创建 server 实例后,调用注册函数 registerCalculatorTools(server); registerWebFetcherTools(server); // ... 其他注册 registerWeatherTools(server); // 添加这一行

第四步:配置与测试

  1. .env文件中添加WEATHER_API_KEY=your_key_here
  2. 运行npm run build编译TypeScript。
  3. 在你的AI客户端(如Claude Code)中重启MCP连接。
  4. 现在,当你问AI“今天北京天气怎么样?”时,它应该能自动调用get_weather工具并返回结果。

4.2 工具设计的黄金法则

根据Starter Kit的范例和社区最佳实践,总结出以下设计法则:

  1. 描述即契约:工具名和参数描述要极其精确。AI完全依赖这些文本来理解工具用途。避免使用“处理数据”这种模糊描述,改用“根据用户ID从数据库查询订单历史”。
  2. 失败要优雅:永远使用failure()返回错误,并提供可操作的提示。例如,不要只返回“数据库错误”,而是“无法连接数据库,请检查 DATABASE_PATH 环境变量是否指向有效的SQLite文件”。
  3. 输出为AI优化:返回的JSON结构应清晰、扁平化。避免过深的嵌套,因为AI需要解析这些数据来生成自然语言回复。使用有意义的字段名。
  4. 考虑速率限制:如果你的工具调用外部API,务必在代码中考虑速率限制和重试逻辑,避免因频繁调用导致IP或API密钥被禁。
  5. 环境变量配置:所有可变配置(API密钥、文件路径、服务地址)都应通过环境变量注入,保证代码与配置分离,适应不同部署环境。

5. 部署、调试与集成实战

5.1 本地开发与热重载工作流

高效的开发离不开流畅的反馈循环。Starter Kit提供了npm run dev命令,它会启动TypeScript编译器在监视(watch)模式。当你修改src/目录下的任何.ts文件时,编译器会自动重新编译到dist/目录。

关键点:MCP服务器是通过stdio与客户端通信的常驻进程。仅仅重新编译(dist/index.js更新)并不会让已连接的客户端加载新工具。你需要重启客户端的MCP连接

  • 在Claude Code中:按下Cmd/Ctrl+Shift+P打开命令面板,搜索并执行 “MCP: Restart Servers”。
  • 在Cursor中:通常修改客户端配置(如.cursor/mcp.json)并保存后,Cursor会自动重连。或者,完全重启Cursor编辑器。

一个高效的开发动线是:打开两个终端窗口,一个运行npm run dev,另一个用于触发客户端重启。修改代码 -> 保存(自动编译) -> 重启客户端连接 -> 在AI对话中测试新功能。

5.2 容器化部署:Docker实战

对于希望在不同机器间一致运行,或进行生产部署的用户,Docker是最佳选择。Starter Kit自带的Dockerfile是一个多阶段构建的典范,它先在一个阶段安装依赖并构建,然后在另一个更小的基础镜像中复制运行所需的最小文件,最终生成一个体积小巧、安全的镜像。

构建与运行

# 1. 构建镜像(注意最后的点) docker build -t my-weather-mcp-server . # 2. 运行容器(-i 参数保持stdin开放,对MCP通信至关重要) docker run -i my-weather-mcp-server

注入配置与持久化数据

docker run -i \ -e WEATHER_API_KEY="your_real_key_here" \ -e DATABASE_PATH="/app/data/myapp.db" \ -v /path/on/host/data:/app/data \ my-weather-mcp-server
  • -e设置环境变量。
  • -v将主机目录挂载到容器内,用于持久化SQLite数据库文件。确保主机目录存在且具有适当权限。

实操心得:在Docker中运行MCP服务器时,最常见的错误是忘记-i参数。没有它,容器的标准输入会立即关闭,导致MCP客户端无法与之建立通信。另外,如果工具需要访问主机上的特定文件(如FILE_ROOT),也需要通过-v挂载进去。

5.3 发布为npm包:共享你的工具

如果你开发了一组非常有用的工具(比如专门用于你公司内部系统的MCP工具集),可以将其发布为npm包,让团队成员通过npx一键使用。

发布步骤

  1. 更新package.json:确保name字段是唯一的(如@your-org/your-mcp-tools),main字段指向dist/index.jsfiles字段包含["dist", "README.md"]以限制发布内容。
  2. 登录npm:运行npm login
  3. 发布:运行npm publish(对于scoped包如@your-org/xxx,首次发布可能需要npm publish --access public)。

用户使用方式:用户在他们的项目.mcp.json或客户端设置中配置:

{ "mcpServers": { "company-tools": { "command": "npx", "args": ["-y", "@your-org/your-mcp-tools"] } } }

当AI客户端启动时,它会自动执行npx -y @your-org/your-mcp-tools来下载(如果尚未安装)并运行你的服务器。-y参数是为了避免npm在安装时进行交互式提问。

5.4 与不同AI客户端的集成细节

虽然MCP是标准协议,但不同客户端的配置方式略有不同。

Claude Code:配置通常放在项目根目录或用户家目录的.mcp.json文件中。Claude Code会递归向上查找此文件。配置更改后,需要执行“MCP: Restart Servers”命令。

Cursor:配置通过编辑器设置界面管理(Settings > MCP Servers)。它提供了一个图形化界面来添加和编辑服务器配置,修改后通常会自动生效或提示重启。

Windsurf:作为较新的AI原生编辑器,Windsurf对MCP的支持也在快速迭代。配置方式可能与Cursor类似,请参考其官方文档。

通用调试技巧:如果工具没有出现在客户端中,首先检查:

  1. 服务器进程是否成功启动且无报错?可以尝试直接运行node dist/index.js,观察控制台输出。
  2. 客户端配置中的commandargs路径是否正确?特别是使用绝对路径时。
  3. 环境变量是否设置正确?服务器是否因缺少必要变量而未能注册某些工具?
  4. 查看客户端的日志或开发者工具(如果有),里面可能有来自MCP服务器的错误信息。

6. 进阶模式与性能优化

6.1 实现资源管理与状态保持

MCP服务器默认是无状态的,每个工具调用都是独立的。但有些场景需要保持状态,比如维护一个数据库连接池、缓存外部API的令牌、或者管理一个WebSocket连接。

模式:惰性初始化与缓存可以在模块级别或工具注册函数外声明一个变量,并在第一次需要时初始化。

// src/tools/database-query.ts import Database from 'better-sqlite3'; let dbInstance: Database.Database | null = null; function getDatabase(): Database.Database { if (!dbInstance) { const dbPath = process.env.DATABASE_PATH || './data.db'; dbInstance = new Database(dbPath, { readonly: false }); // 可以在这里执行一些初始化SQL,比如打开WAL模式提升并发性能 dbInstance.pragma('journal_mode = WAL'); } return dbInstance; } // 在工具处理函数中调用 getDatabase() 而不是每次都创建新连接

这种方式避免了每次工具调用都重新建立数据库连接的开销。但需要注意,在长时间运行的服务器中,要考虑连接可能超时或被服务器端断开的情况,需要增加错误恢复逻辑。

6.2 处理长耗时操作与流式响应

某些操作(如处理大文件、执行复杂计算、等待长时间的网络请求)可能超过AI客户端默认的等待时间。MCP协议本身支持异步操作,但工具处理函数需要返回一个Promise。

对于非常长的操作,一个进阶模式是结合MCP的资源(Resources)功能。你可以让工具调用立即返回一个“任务已提交”的响应,并提供一个资源URI(如task://status/12345)。然后,AI客户端可以定期通过resources/get请求来轮询任务状态。Starter Kit主要聚焦于工具,但了解这个模式有助于你设计更复杂的交互。

实操建议:对于耗时超过10秒的操作,应考虑这种异步模式。对于5-10秒内的操作,确保工具设置了合理的超时,并返回清晰的“操作进行中,请稍后重试”的提示。

6.3 性能监控与日志记录

在生产环境中,你可能需要知道工具被调用的频率、成功率、耗时等信息。

简单的日志注入:你可以在每个工具处理函数的开头和结尾记录时间戳和参数(注意过滤敏感信息)。

async ({ query, limit }) => { const startTime = Date.now(); const toolName = "my_tool_name"; console.error(`[MCP][${toolName}] Start. Query: ${query.substring(0, 50)}...`); try { // ... 工具逻辑 const duration = Date.now() - startTime; console.error(`[MCP][${toolName}] Success. Duration: ${duration}ms`); return success(result); } catch (err) { const duration = Date.now() - startTime; console.error(`[MCP][${toolName}] Failed after ${duration}ms. Error:`, err); return failure(...); } }

使用console.errorconsole.warn输出到stderr,这样不会干扰通过stdout传输的MCP协议数据。这些日志可以被Docker或系统服务管理器(如systemd)捕获并转发到日志聚合系统。

6.4 安全加固进阶

除了Starter Kit内置的安全措施,在部署到生产环境前还应考虑:

  1. 工具权限细分:通过环境变量控制哪些工具可用。例如,设置ENABLE_FILE_WRITE=false来禁用write_file工具,只保留只读权限。
  2. 输入净化:对于文件路径、URL等参数,在Zod验证之后,可以增加额外的净化逻辑,比如移除多余的...,或确保URL的协议是允许的(只允许http/https)。
  3. 请求限流:如果你的服务器可能被频繁调用,可以在入口层面(index.ts)或每个工具内部添加简单的限流逻辑,防止滥用。
  4. 依赖安全扫描:定期使用npm audit或集成Snyk等工具检查项目依赖是否存在已知安全漏洞。

7. 常见问题排查与解决实录

在实际开发和集成过程中,你难免会遇到一些问题。以下是我在多次使用和教学过程中总结的典型问题及其解决方案。

7.1 工具不显示在AI客户端

这是最常见的问题,表现为你配置了服务器,但AI对话中看不到新加的工具。

排查步骤

  1. 检查服务器启动日志:直接运行node dist/index.js。如果服务器立即退出或有红色错误输出,说明编译或运行时出错。常见原因有:
    • TypeScript编译错误:运行npm run build查看详细错误。
    • 缺少依赖:运行npm install确保所有依赖(包括可选依赖)已安装。
    • 环境变量缺失:如果工具代码中强制要求某个环境变量而未设置,可能导致模块初始化失败,进而工具注册被跳过。检查控制台输出。
  2. 检查客户端配置
    • 路径问题:确保args中的路径是绝对路径。在配置中使用__dirnameprocess.cwd()来构造绝对路径更可靠。
    • 命令格式command如果是nodeargs应该是["/absolute/path/to/dist/index.js"]。如果使用npx,格式应为["-y", "package-name"]
  3. 重启客户端连接:修改配置或服务器代码后,必须重启客户端的MCP连接。仅仅重启编辑器可能不够。
  4. 查看客户端MCP日志:一些客户端(如Claude Code的开发者模式)会输出MCP通信日志。查看其中是否有tools/list的请求和响应,响应中是否包含你的工具。

7.2 工具调用失败或返回意外错误

工具出现了,但调用时出错。

排查步骤

  1. 审查工具返回的错误信息:AI通常会原样展示failure()返回的contenterror字段。这是第一手调试信息。
  2. 检查服务器端日志:如前所述,在工具中添加console.error日志,查看实际执行过程中的错误。
  3. 参数验证问题:确认AI传递的参数完全符合Zod模式定义。例如,一个定义为z.number().int().positive()的参数,如果AI传递了0-5,Zod验证会失败,错误会通过failure()返回。确保你的.describe()足够清晰,引导AI输入正确的值。
  4. 异步操作未正确处理:确保所有异步操作都正确使用了await,并且工具处理函数是async函数。未处理的Promise拒绝(Unhandled Promise Rejection)可能导致进程不稳定。

7.3 性能问题:响应缓慢或超时

可能原因与解决方案

问题现象可能原因解决方案
所有工具都慢服务器启动慢或首次工具初始化慢检查是否有耗时的同步初始化(如加载大文件到内存)。将其改为惰性加载或在启动时异步进行。
特定网络工具慢外部API响应慢或网络不佳为该工具设置更短的超时(如5秒),并返回友好的超时提示。考虑引入缓存机制,对相同请求缓存一段时间的结果。
文件操作工具慢操作的文件非常大或目录很深read_file添加文件大小限制,超过则拒绝读取。为list_files的递归模式添加深度和总数限制。
数据库查询慢查询未优化或数据量大确保查询使用了索引。对于复杂查询,考虑在工具中限制返回的行数(LIMIT)。

7.4 在Docker中运行失败

典型错误与解决

  • 错误:Error: spawn node ENOENT:Docker镜像中未安装Node.js。确保你的Dockerfile基于Node.js官方镜像(如node:20-alpine)。
  • 错误:服务器启动后立即退出:很可能缺少-i参数。MCP必须通过stdio通信,没有交互式输入(-i)容器会立即退出。
  • 错误:无法写入文件或数据库:容器内用户权限不足,或挂载卷的权限不正确。检查Docker命令中的-v挂载路径,确保容器内进程有读写权限。有时需要运行chmod调整主机目录权限,或在Dockerfile中用USER指令指定非root用户运行。
  • 错误:环境变量未生效:确保在docker run命令中用-e正确传递了所有必要的环境变量。也可以在Dockerfile中使用ENV指令设置默认值,但敏感信息(如API密钥)仍应通过-e传入。

7.5 扩展工具时的设计困惑

Q:我应该把多个相关功能放在一个工具里,还是拆成多个工具?A:遵循“单一职责原则”。如果一个操作有显著不同的意图和参数集,就拆分成多个工具。例如,“搜索文件”和“读取文件”是两个独立的工具。但如果只是同一操作的不同模式(如“列出文件”支持递归和非递归),可以通过一个可选参数来控制。判断标准是:看AI是否能从工具描述中清晰区分何时使用它。

Q:我的工具需要访问多个外部服务,代码变得很臃肿怎么办?A:遵循Starter Kit的模块化思想。将对外部服务的调用封装成独立的服务类或函数(如WeatherService,GitHubService),放在src/services/目录下。工具模块只负责参数验证、调用服务、格式化响应和错误处理。这样代码更清晰,也便于单独测试服务层。

Q:如何让AI更“聪明”地使用我的工具?A:除了写好工具描述和参数描述,你还可以利用项目中的CLAUDE.md文件。这个文件是专门用来“教育”Claude等AI关于你项目特殊用法的。你可以在里面详细说明每个工具的最佳使用场景、示例、常见参数值以及它们之间的组合使用方式。AI在分析你的项目时可能会参考这个文件,从而更准确地调用工具。

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

2026年4月大模型格局演变:GPT-5.5与DeepSeek-V4的双星闪耀

上一篇:DeepSeek-V4技术突破:国产大模型百万上下文普惠时代 下一篇:未完待续 核心结论:2026年4月成为大模型技术的"超级月"——OpenAI GPT-5.5(4月23日)、DeepSeek-V4(4月24日&#x…

作者头像 李华
网站建设 2026/5/2 12:03:27

AI助手安全支付实践:基于MCP与零知识架构的Ovra Pay集成指南

1. 项目概述:为AI助手赋予安全的支付能力 最近在折腾AI助手(Agent)的自动化工作流时,遇到了一个挺有意思的痛点:如何让AI助手安全地帮我完成在线支付?比如,我让助手帮我订个外卖、买本书&#…

作者头像 李华
网站建设 2026/5/2 11:58:17

终极暗黑3自动化助手:5分钟快速配置D3keyHelper完整指南

终极暗黑3自动化助手:5分钟快速配置D3keyHelper完整指南 【免费下载链接】D3keyHelper D3KeyHelper是一个有图形界面,可自定义配置的暗黑3鼠标宏工具。 项目地址: https://gitcode.com/gh_mirrors/d3/D3keyHelper 厌倦了在《暗黑破坏神3》中反复点…

作者头像 李华
网站建设 2026/5/2 11:58:16

Obsidian PDF++:3步打造你的智能PDF标注系统

Obsidian PDF:3步打造你的智能PDF标注系统 【免费下载链接】obsidian-pdf-plus PDF: the most Obsidian-native PDF annotation & viewing tool ever. Comes with optional Vim keybindings. 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-pdf-plus …

作者头像 李华