当前位置: 首页 > article >正文

基于wet-mcp构建AI工具服务器:MCP协议实践指南

1. 项目概述一个为AI应用量身定制的“湿”MCP服务器最近在折腾AI应用开发特别是想让大语言模型LLM能更灵活地调用外部工具和API时发现了一个挺有意思的项目n24q02m/wet-mcp。这个项目名听起来有点抽象但它的定位非常明确——它是一个“湿”的MCPModel Context Protocol服务器实现。MCP协议简单来说就是为AI模型比如ChatGPT、Claude等定义了一套标准化的方式来发现、描述和调用外部工具Tools和资源Resources。你可以把它想象成给AI模型装上了一套标准化的“插件系统”接口。而“湿”wet这个前缀在开源社区里通常用来指代某个协议或标准的“服务器端”实现与之相对的“干”dry则可能指客户端或SDK。所以wet-mcp就是一个功能完备的MCP服务器它负责实际承载和暴露那些可供AI模型使用的工具。这个项目的核心价值在于它让开发者能够以一种统一、标准化的方式将自己开发的任何功能比如查询数据库、调用第三方API、执行系统命令、读取文件等封装成MCP工具然后让任何支持MCP协议的AI应用如Claude Desktop、Cursor等无缝调用。这极大地简化了AI能力扩展的复杂度避免了为每个AI平台重复开发适配插件。2. MCP协议核心思想与wet-mcp的定位2.1 为什么需要MCP解决AI工具调用的“碎片化”难题在接触MCP之前给AI模型扩展功能是个挺头疼的事。每个AI平台OpenAI的GPTs、Anthropic的Claude、各类开源模型的前端都有自己的一套插件或工具调用机制。如果你想让你写的“天气查询”功能被多个AI助手使用很可能需要为每个平台单独开发一遍适配代码。这不仅重复劳动而且维护成本极高。MCP协议的出现就是为了解决这个“碎片化”问题。它定义了一套与具体AI模型和前端应用无关的、基于JSON-RPC的通信协议。这套协议规定了工具Tools的发现与描述服务器告诉客户端AI应用我这里有哪些工具可用每个工具叫什么名字需要什么参数。工具的执行Call客户端发起工具调用请求服务器执行并返回结果。资源Resources的提供服务器还可以提供一些只读的数据资源如文件内容、数据库视图供AI模型在思考时参考。wet-mcp项目就是这套协议的服务器端的一个具体实现。它帮你处理了所有底层的协议通信、消息序列化、连接管理等繁琐工作。作为开发者你只需要关注最核心的业务逻辑实现你的工具函数。2.2 wet-mcp的技术栈与设计哲学从项目仓库来看wet-mcp很可能是一个用TypeScript/JavaScript开发的项目这是MCP生态中最活跃的语言。它的设计哲学应该是“约定优于配置”和“开发者友好”。它通常会提供一个清晰的框架让你通过简单的类定义或函数装饰器来声明一个工具。例如你可能只需要写一个这样的函数// 伪代码示例示意wet-mcp可能的用法 import { McpServer, Tool } from wet-mcp; const server new McpServer({ name: 我的工具服务器, version: 1.0.0 }); // 使用装饰器或方法来声明一个工具 Tool({ name: get_weather, description: 获取指定城市的当前天气, inputSchema: { type: object, properties: { city: { type: string, description: 城市名称 } }, required: [city] } }) async function getWeather({ city }) { // 这里实现实际的天气API调用逻辑 const response await fetch(https://api.weather.com/v1?city${city}); const data await response.json(); return 城市 ${city} 的天气是${data.condition}温度 ${data.temp}°C。; } // 将工具注册到服务器 server.registerTool(getWeather); // 启动服务器 server.start();通过这种方式wet-mcp将复杂的协议交互抽象成了简单的业务代码编写。它内部会负责将你的工具函数和它的描述信息通过MCP协议规定的tools/list方法暴露给客户端。当收到客户端的tools/call请求时自动匹配到对应的工具函数传入参数执行它并将返回值封装成标准响应。管理服务器与客户端之间的WebSocket或Stdio连接处理心跳、错误和生命周期事件。这种设计让开发者能快速构建出生产可用的MCP服务器而无需深究协议细节。3. 使用wet-mcp构建你的第一个工具服务器从零到一理论说了这么多我们来点实际的。假设我们要用wet-mcp构建一个简单的服务器它提供一个“计算器”工具和一个“获取系统时间”工具。3.1 环境准备与项目初始化首先确保你有一个Node.js环境版本18或以上。然后创建一个新的项目目录并初始化。mkdir my-mcp-server cd my-mcp-server npm init -y接下来安装wet-mcp包。由于它是一个相对具体的实现我们需要查看其官方仓库获取准确的安装命令。假设它已经发布到npm我们可以这样安装npm install n24q02m/wet-mcp # 或者如果它尚未发布到npm你可能需要从GitHub直接安装 # npm install github:n24q02m/wet-mcp同时我们安装TypeScript和相关类型定义如果项目是TS写的以便获得更好的开发体验。npm install typescript types/node ts-node --save-dev npx tsc --init3.2 核心工具的实现与注册现在创建我们的主文件src/server.ts。import { McpServer, Tool } from n24q02m/wet-mcp; // 1. 创建MCP服务器实例 const server new McpServer({ name: 示例工具服务器, version: 0.1.0 }); // 2. 实现并注册“计算器”工具 // 假设wet-mcp使用装饰器模式。具体API请以官方文档为准。 Tool({ name: calculator, description: 执行简单的数学运算。支持加()、减(-)、乘(*)、除(/), inputSchema: { type: object, properties: { expression: { type: string, description: 数学表达式例如 3 5 * 2。注意为安全起见请避免使用复杂函数或危险语法。 } }, required: [expression] } }) async function calculate({ expression }: { expression: string }) { // 重要在生产环境中直接eval是极其危险的这里仅为演示。 // 实际应用应该使用安全的数学表达式解析库如 math.js 或 expr-eval。 try { // 简易的、有限制的计算。切勿用于处理用户不可信的输入 const sanitized expression.replace(/[^0-9\-*/().\s]/g, ); const result eval(sanitized); return { content: [{ type: text, text: 表达式 ${expression} 的计算结果是${result} }] }; } catch (error) { return { content: [{ type: text, text: 计算失败${error.message}。请检查表达式格式。 }], isError: true }; } } // 3. 实现并注册“获取时间”工具 Tool({ name: get_current_time, description: 获取当前的服务器系统时间和日期。, inputSchema: { type: object, properties: {} // 这个工具不需要输入参数 } }) async function getCurrentTime() { const now new Date(); const timeString now.toLocaleString(zh-CN, { timeZone: Asia/Shanghai, year: numeric, month: long, day: numeric, hour: 2-digit, minute: 2-digit, second: 2-digit, hour12: false }); return { content: [{ type: text, text: 当前服务器时间北京时间是${timeString} }] }; } // 4. 将工具函数注册到服务器 // 具体注册方法取决于wet-mcp的API设计可能是 // server.registerTool(calculate); // server.registerTool(getCurrentTime); // 或者通过装饰器已自动注册。 // 5. 启动服务器 // 通常MCP服务器通过stdio或socket与客户端通信。 // 例如启动一个stdio服务器这是与Claude Desktop等客户端集成的常见方式。 server.start({ transport: stdio // 通过标准输入输出进行通信 }); console.error(MCP工具服务器已启动等待客户端连接...);重要安全提示上面的计算器工具为了演示简单使用了eval这在生产环境是绝对禁止的会带来严重的代码注入安全风险。真实项目中务必使用像math.js或expr-eval这样安全的表达式求值库。3.3 配置与运行为了让AI客户端如Claude Desktop能发现并连接我们的服务器通常需要创建一个配置文件。对于Claude Desktop在特定目录如~/Library/Application Support/Claude/claude_desktop_config.jsonon macOS添加配置{ mcpServers: { my-example-server: { command: node, args: [ /ABSOLUTE/PATH/TO/YOUR/PROJECT/dist/server.js // 指向编译后的JS文件 ], env: { NODE_ENV: production } } } }然后编译并运行我们的TypeScript代码npx tsc # 编译 # 或者直接使用ts-node运行 npx ts-node src/server.ts如果一切正常当你在Claude Desktop中询问“请用计算器算一下3加5乘以2”时Claude应该能识别到可用的calculator工具并调用它得到结果“13”。4. 深入wet-mcp高级特性与最佳实践一个基础的服务器跑起来后我们会面临更多实际问题。wet-mcp作为成熟的服务器实现应该提供了一系列高级特性来应对复杂场景。4.1 资源Resources的提供与管理除了工具MCP协议另一个核心概念是“资源”。资源是只读的数据片段AI模型可以在规划行动或生成回答前先读取它们作为上下文。例如一个“项目文件阅读器”服务器可以提供文件内容作为资源。在wet-mcp中注册资源可能看起来像这样import { Resource } from n24q02m/wet-mcp; Resource({ uri: file:///project/README.md, name: 项目自述文件, description: 本项目的主要说明文档, mimeType: text/markdown }) async function provideReadme() { const fs await import(fs/promises); try { const content await fs.readFile(./README.md, utf-8); return { contents: [{ uri: file:///project/README.md, mimeType: text/markdown, text: content }] }; } catch (error) { // 处理文件不存在等情况 return { contents: [], isError: true }; } } // 注册资源 // server.registerResource(provideReadme);客户端可以通过resources/list和resources/read方法来浏览和读取这些资源。这对于让AI了解系统状态、配置文件内容或数据库Schema非常有用。4.2 工具调用的异步、流式与进度反馈有些工具执行起来很耗时比如“训练一个机器学习模型”或“下载一个大文件”。MCP协议支持异步工具调用和进度反馈。wet-mcp应该提供相应的机制来支持这种长时间运行的任务。一种常见的模式是工具调用立即返回一个jobId然后服务器通过独立的通知notifications来推送进度更新和最终结果。// 伪代码展示长任务处理思路 Tool({ name: long_running_task, description: 执行一个模拟的长耗时任务 }) async function longTask({ steps }: { steps: number }) { const jobId generateJobId(); // 立即返回告诉客户端任务已开始 server.sendNotification(task/progress, { jobId, progress: 0, status: started }); // 模拟耗时操作 for (let i 1; i steps; i) { await delay(1000); // 模拟每秒一步 const progress i / steps; server.sendNotification(task/progress, { jobId, progress, status: Processing step ${i} }); } // 任务完成发送最终结果通知 server.sendNotification(task/complete, { jobId, result: { content: [{ type: text, text: 长任务完成共执行 ${steps} 步。 }] } }); // 工具调用本身可以返回一个初始响应 return { content: [{ type: text, text: 长任务已启动任务ID: ${jobId}。请等待进度通知。 }], metadata: { jobId } }; }这种模式能极大地提升用户体验让AI助手可以实时向用户反馈“任务正在处理中已完成50%”。4.3 错误处理、日志与监控一个健壮的服务器必须有完善的错误处理。wet-mcp框架应该能捕获工具函数中抛出的异常并将其转化为MCP协议标准的错误响应包含code和message。作为开发者我们应该在工具内部进行细致的错误捕获和分类比如参数验证错误、网络超时、权限不足等返回不同的错误信息。记录详细的日志使用如winston或pino等日志库记录每一个工具调用的请求、响应、耗时和错误。这对于调试和监控至关重要。添加监控指标可以使用prom-client暴露Prometheus指标监控工具调用次数、成功率、延迟等。import winston from winston; const logger winston.createLogger({ level: info, format: winston.format.json(), transports: [new winston.transports.File({ filename: mcp-server.log })] }); // 在工具函数中 Tool({ name: safe_calculator }) async function safeCalculate({ expression }: { expression: string }) { const startTime Date.now(); try { // 使用安全的数学库 const math await import(mathjs); const result math.evaluate(expression); const duration Date.now() - startTime; logger.info(Tool call succeeded, { tool: safe_calculator, expression, result, durationMs: duration }); return { content: [{ type: text, text: 结果: ${result} }] }; } catch (error: any) { const duration Date.now() - startTime; logger.error(Tool call failed, { tool: safe_calculator, expression, error: error.message, durationMs: duration }); // 返回结构化的错误信息 return { content: [{ type: text, text: 计算错误: ${error.message} }], isError: true, // MCP协议可能允许传递更详细的错误信息 // error: { code: INVALID_EXPRESSION, message: error.message } }; } }4.4 安全性考量与权限控制将内部工具暴露给AI模型是一个需要严肃对待的安全问题。wet-mcp服务器作为网关必须实施严格的安全措施。输入验证与净化这是第一道防线。对所有工具的参数进行严格的模式验证利用inputSchema并净化所有输入防止注入攻击。像上面的计算器绝对不能用eval。身份认证与授权虽然MCP协议本身可能不强制但在生产环境中你的服务器应该验证连接客户端的身份。例如可以通过共享密钥、TLS客户端证书或启动时传入的令牌来实现。const server new McpServer({ // ... 其他配置 authentication: { type: token, token: process.env.MCP_SERVER_TOKEN // 从环境变量读取密钥 } });在客户端配置中也需要包含这个令牌。工具级别的权限不是所有连接过来的AI都有权调用所有工具。可以实现一个简单的权限映射根据客户端标识来过滤可用的工具列表。网络隔离确保MCP服务器运行在受信任的网络环境中不要将其直接暴露在公网。通常它只与本地安装的AI桌面应用通信。5. 实战构建一个实用的“智能运维助手”MCP服务器让我们综合运用以上知识设计一个稍微复杂点的、有实用价值的MCP服务器一个智能运维助手。它可以提供以下工具list_processes: 列出系统进程受限例如只列出当前用户进程。disk_usage: 查看磁盘使用情况。fetch_logs: 获取指定应用最近N行的日志。restart_service: 重启某个系统服务需要高权限需谨慎。5.1 项目结构与核心工具实现我们创建一个更结构化的项目。smart-ops-mcp/ ├── package.json ├── tsconfig.json ├── src/ │ ├── index.ts # 服务器入口 │ ├── tools/ # 工具实现目录 │ │ ├── system.ts # 系统相关工具 │ │ ├── logs.ts # 日志相关工具 │ │ └── services.ts # 服务管理工具 │ └── utils/ │ ├── security.ts # 安全验证工具 │ └── logger.ts # 日志工具 └── config/ └── permissions.json # 权限配置文件src/tools/system.ts- 系统信息工具import { Tool } from n24q02m/wet-mcp; import { exec } from child_process; import { promisify } from util; const execAsync promisify(exec); Tool({ name: list_processes, description: 列出当前用户运行的前20个进程按CPU使用率排序。, inputSchema: { type: object, properties: { limit: { type: number, description: 返回的进程数量默认20, default: 20 } } } }) export async function listProcesses({ limit 20 }: { limit?: number }) { // 注意不同操作系统命令不同这里以Linux/macOS为例 const command ps aux --sort-%cpu | head -n ${limit 1}; // 1 为了跳过标题行 try { const { stdout } await execAsync(command); return { content: [{ type: text, text: 当前用户的前${limit}个进程按CPU排序\n\\\\n${stdout}\n\\\ }] }; } catch (error: any) { return { content: [{ type: text, text: 执行失败: ${error.message} }], isError: true }; } } Tool({ name: disk_usage, description: 查看各磁盘分区的使用情况。, inputSchema: { type: object, properties: {} } }) export async function diskUsage() { const command df -h; try { const { stdout } await execAsync(command); return { content: [{ type: text, text: 磁盘使用情况\n\\\\n${stdout}\n\\\ }] }; } catch (error: any) { return { content: [{ type: text, text: 执行失败: ${error.message} }], isError: true }; } }src/tools/logs.ts- 日志工具import { Tool } from n24q02m/wet-mcp; import { readFile } from fs/promises; import { join } from path; // 假设我们定义了几个可以查看的日志应用 const ALLOWED_APPS [nginx, myapp, system] as const; type AppName typeof ALLOWED_APPS[number]; const LOG_PATHS: RecordAppName, string { nginx: /var/log/nginx/access.log, myapp: /var/log/myapp/app.log, system: /var/log/syslog }; Tool({ name: fetch_logs, description: 获取指定应用程序日志的最后若干行。, inputSchema: { type: object, properties: { app: { type: string, description: 应用程序名称可选值: ${ALLOWED_APPS.join(, )}, enum: [...ALLOWED_APPS] }, lines: { type: number, description: 要获取的行数默认50行, default: 50 } }, required: [app] } }) export async function fetchLogs({ app, lines 50 }: { app: string; lines?: number }) { // 1. 输入验证 if (!ALLOWED_APPS.includes(app as AppName)) { return { content: [{ type: text, text: 不允许的应用程序名称。请使用: ${ALLOWED_APPS.join(, )} }], isError: true }; } const logPath LOG_PATHS[app as AppName]; const command tail -n ${lines} ${logPath}; try { const { exec } await import(child_process); const { promisify } await import(util); const execAsync promisify(exec); const { stdout } await execAsync(command); return { content: [{ type: text, text: 应用程序 **${app}** 的最后 ${lines} 行日志\n\\\\n${stdout}\n\\\ }] }; } catch (error: any) { // 更友好的错误信息 if (error.code ENOENT) { return { content: [{ type: text, text: 日志文件不存在: ${logPath} }], isError: true }; } if (error.code EACCES) { return { content: [{ type: text, text: 权限不足无法读取日志文件: ${logPath} }], isError: true }; } return { content: [{ type: text, text: 读取日志失败: ${error.message} }], isError: true }; } }5.2 权限控制与安全增强对于restart_service这种高危操作我们必须加入权限控制。我们可以设计一个简单的基于令牌的权限系统。config/permissions.json{ tokens: { claude-desktop-readonly: { allowedTools: [list_processes, disk_usage, fetch_logs] }, claude-desktop-admin: { allowedTools: [list_processes, disk_usage, fetch_logs, restart_service] } } }src/utils/security.tsimport permissions from ../../config/permissions.json; export interface ClientContext { token?: string; clientId?: string; } export function getClientPermissions(token: string | undefined) { if (!token) { return { allowedTools: [] }; // 未认证客户端无权限 } const clientPerms (permissions as any).tokens[token]; return clientPerms || { allowedTools: [] }; } export function canCallTool(clientPerms: { allowedTools: string[] }, toolName: string): boolean { return clientPerms.allowedTools.includes(toolName); }然后在服务器初始化或工具调用时注入并检查权限。wet-mcp框架可能提供了中间件或钩子机制来实现这一点。// 伪代码在工具调用前进行权限检查 server.onToolCall((call, context) { const perms getClientPermissions(context.token); if (!canCallTool(perms, call.name)) { throw new Error(客户端无权调用工具: ${call.name}); } // 否则继续执行工具 });5.3 服务器入口与配置整合src/index.tsimport { McpServer } from n24q02m/wet-mcp; import { listProcesses, diskUsage } from ./tools/system; import { fetchLogs } from ./tools/logs; import { restartService } from ./tools/services; import { setupErrorHandling, setupLogging } from ./utils/logger; async function main() { // 初始化服务器 const server new McpServer({ name: 智能运维助手, version: 1.0.0, // 假设wet-mcp支持自定义上下文和认证 authentication: { type: token-header // 客户端通过Header传递令牌 } }); // 设置全局错误处理和日志假设框架支持 setupErrorHandling(server); setupLogging(server); // 注册所有工具 // 注意实际注册方式取决于wet-mcp的API这里仅为示意 server.registerTool(listProcesses); server.registerTool(diskUsage); server.registerTool(fetchLogs); server.registerTool(restartService); // 这个工具受权限保护 // 启动服务器 const transportType process.env.MCP_TRANSPORT || stdio; server.start({ transport: transportType as any }); console.error(智能运维MCP服务器已启动使用 ${transportType} 传输。); } main().catch(err { console.error(服务器启动失败:, err); process.exit(1); });5.4 客户端配置与测试最后在Claude Desktop的配置中我们需要为这个运维服务器配置两个条目对应不同的权限令牌。{ mcpServers: { ops-assistant-readonly: { command: node, args: [/path/to/smart-ops-mcp/dist/index.js], env: { MCP_TRANSPORT: stdio, MCP_AUTH_TOKEN: claude-desktop-readonly // 只读令牌 } }, ops-assistant-admin: { command: node, args: [/path/to/smart-ops-mcp/dist/index.js], env: { MCP_TRANSPORT: stdio, MCP_AUTH_TOKEN: claude-desktop-admin // 管理员令牌 } } } }这样当你用Claude Desktop聊天时如果你以只读身份连接尝试让AI重启服务AI会告诉你没有可用的工具。而用管理员身份连接时则可以执行全套操作。这实现了基本的分权管理。6. 调试、部署与性能优化6.1 调试技巧如何与你的MCP服务器“对话”开发MCP服务器时一个很大的挑战是如何独立于AI客户端进行调试。你可以使用一些MCP客户端测试工具比如modelcontextprotocol/sdk提供的CLI工具或者自己写一个简单的测试脚本。一个更直接的方法是利用MCP通常支持的stdio传输我们可以模拟一个客户端// test-client.js const { spawn } require(child_process); // 启动你的MCP服务器进程 const serverProcess spawn(node, [dist/index.js], { stdio: [pipe, pipe, inherit] // 继承stderr以便看日志 }); // 向服务器发送一个原始的MCP请求JSON-RPC格式 function sendRequest(method, params) { const request { jsonrpc: 2.0, id: Date.now(), method, params }; const requestStr JSON.stringify(request) \n; console.log(发送请求:, requestStr); serverProcess.stdin.write(requestStr); } // 监听服务器的响应 serverProcess.stdout.on(data, (data) { const lines data.toString().split(\n).filter(line line.trim()); for (const line of lines) { try { const response JSON.parse(line); console.log(收到响应:, JSON.stringify(response, null, 2)); } catch (e) { console.log(非JSON输出:, line); } } }); // 发送初始化请求 setTimeout(() { sendRequest(initialize, { protocolVersion: 1.0, clientInfo: { name: TestClient, version: 1.0 } }); // 稍后请求工具列表 setTimeout(() { sendRequest(tools/list, {}); }, 100); }, 500); // 10秒后退出 setTimeout(() { serverProcess.kill(); process.exit(0); }, 10000);运行这个脚本你可以看到服务器返回的原始协议数据这对于排查协议层面的问题非常有用。6.2 部署考量进程管理、健康检查与高可用当你的MCP服务器准备投入生产环境比如给团队使用就需要考虑部署问题。进程管理使用pm2、systemd或docker来管理服务器进程确保崩溃后能自动重启。# 使用pm2的例子 pm2 start dist/index.js --name mcp-ops-server --interpreter node pm2 save pm2 startup健康检查虽然MCP协议可能没有标准的健康检查端点但你可以让服务器在另一个端口提供一个简单的HTTP健康检查接口。import express from express; const healthApp express(); healthApp.get(/health, (req, res) { res.json({ status: ok, tools: server.getRegisteredToolNames() }); }); healthApp.listen(8080, () { console.log(健康检查服务运行在 8080 端口); });资源限制为Node.js进程设置内存和CPU限制防止某个工具调用耗尽系统资源。# 使用docker运行时的资源限制 docker run --memory512m --cpus1 my-mcp-server配置管理将服务器配置如令牌、日志路径、允许的工具外部化使用环境变量或配置文件便于不同环境部署。6.3 性能优化应对高并发与长尾请求如果多个AI客户端同时连接或者某些工具执行很慢性能就成为关键。连接池与资源复用对于需要访问数据库或外部API的工具使用连接池如数据库连接池、HTTP连接池来避免频繁创建销毁连接的开销。工具执行超时为每个工具调用设置合理的超时时间防止恶意或错误的请求长时间占用服务器资源。wet-mcp框架可能支持全局或工具级别的超时设置。异步与非阻塞确保你的工具函数是异步的async不要执行同步的阻塞操作如同步文件读写、长时间CPU计算。如果必须执行CPU密集型任务考虑使用工作线程Worker Threads或将其委托给外部服务。结果缓存对于某些读多写少、数据变化不频繁的工具如disk_usage可以考虑添加一个短期缓存比如5秒减少对底层系统的直接调用。监控与告警集成APM工具如OpenTelemetry来监控工具调用的延迟、错误率和资源使用情况设置告警阈值。7. 生态整合与未来展望wet-mcp作为MCP协议的服务器实现其价值很大程度上取决于整个MCP生态的发展。目前除了Claude Desktop越来越多的AI应用和平台开始支持MCP协议。你可以将你的wet-mcp服务器发布为一个独立的npm包这样其他开发者可以轻松安装并集成到他们的AI工作流中。例如npm install smart-ops-mcp-server然后在他们的Claude Desktop配置中只需要简单引用{ mcpServers: { smart-ops: { command: npx, args: [-y, smart-ops-mcp-server] } } }未来随着MCP协议的演进我们可能会看到更丰富的工具类型支持流式响应、双向通信服务器主动推送信息给AI、工具组合编排。标准化的身份验证和授权协议层可能定义更完善的Auth机制。服务发现与注册中心出现公共或私有的MCP服务器注册中心AI助手可以动态发现和调用可用的工具服务。可视化工具编排出现图形化界面让非开发者也能通过拖拽方式组合不同的MCP工具创建复杂的AI工作流。对于开发者而言现在基于wet-mcp这样的稳定实现来构建工具服务器是在为这个开放的、可互操作的AI未来打下基础。你创造的每一个工具都可能成为未来某个智能工作流中不可或缺的一环。

相关文章:

基于wet-mcp构建AI工具服务器:MCP协议实践指南

1. 项目概述:一个为AI应用量身定制的“湿”MCP服务器最近在折腾AI应用开发,特别是想让大语言模型(LLM)能更灵活地调用外部工具和API时,发现了一个挺有意思的项目:n24q02m/wet-mcp。这个项目名听起来有点抽象…...

Tailwind CSS 尺寸控制

Tailwind CSS 尺寸控制学习笔记 一、尺寸体系概览 Tailwind CSS 的尺寸系统涵盖 宽度 (Width)、高度 (Height)、最小/最大尺寸 以及 任意值,提供从固定值到百分比的完整控制能力。二、宽度 (Width) 1. 固定宽度类名CSS 属性像素值说明w-0width: 00px零宽度w-pxwidth…...

不止是U盘!用小米手机OTG连接键盘鼠标,秒变移动办公小电脑(含Type-C线选购指南)

小米手机OTG功能全攻略:从移动办公到娱乐扩展的终极指南 你是否曾经在咖啡馆临时需要修改文档,却苦于手机触屏输入效率低下?或是出差途中急需从U盘读取一份重要合同,却找不到电脑?小米手机的OTG功能或许能成为你的移动…...

给OpenWrt LuCI界面写个插件:从看懂CBI模型到实现一个配置页(附完整代码)

OpenWrt LuCI插件开发实战:从CBI模型解析到自定义配置页实现 在智能路由器的世界里,OpenWrt以其开源特性和高度可定制性赢得了开发者的青睐。而LuCI作为其官方Web管理界面,通过简洁的Lua框架为路由器功能提供了可视化操作入口。但当我们需要为…...

1500对工业图像:DeepPCB如何重塑电路板缺陷检测的技术范式

1500对工业图像:DeepPCB如何重塑电路板缺陷检测的技术范式 【免费下载链接】DeepPCB A PCB defect dataset. 项目地址: https://gitcode.com/gh_mirrors/de/DeepPCB 在电子产品制造领域,PCB质量检测一直是制约生产效率和产品可靠性的关键瓶颈。传…...

Taotoken用量看板如何帮助团队清晰掌握各模型消耗详情

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 Taotoken用量看板如何帮助团队清晰掌握各模型消耗详情 对于依赖大模型进行开发的团队而言,成本控制与资源优化是持续面…...

避坑指南:Android分屏开发中,SystemServer端那些容易忽略的Task生命周期与配置变更细节

Android分屏开发避坑指南:SystemServer端Task生命周期与配置变更的深度解析 在Android多窗口生态中,分屏模式因其高效的屏幕空间利用率而备受开发者青睐。然而,当应用需要适配分屏功能时,许多开发者往往只关注客户端UI适配&#x…...

Godot开发者必备:Awesome Godot资源合集使用指南

1. 项目概述:一份为Godot开发者量身定制的“藏宝图”如果你正在使用Godot引擎开发游戏,或者对这个开源、免费且功能强大的游戏引擎感兴趣,那么你很可能已经体会过在茫茫互联网中寻找高质量资源、插件和参考项目的痛苦。官方文档固然详尽&…...

UVM验证中的“交通指挥官”:深入浅出搞懂virtual sequence与virtual sequencer的协同调度

UVM验证中的“交通指挥官”:深入浅出搞懂virtual sequence与virtual sequencer的协同调度 在复杂的芯片验证环境中,多个接口协议需要并行工作,模拟真实场景下的数据交互。想象一下,一个SoC芯片同时处理AHB总线传输、APB寄存器配置…...

从惠普档案火灾看电子测试测量技术遗产的保护与传承

1. 一场大火与一段历史的消逝:从惠普档案损毁看技术遗产的脆弱性2017年10月,加州葡萄酒乡那场被称为“塔布斯”的山火,不仅吞噬了无数家园与生命,也在不经意间,灼伤了现代电子工程史的一角。当烈焰席卷位于圣罗莎的是德…...

ICode竞赛Python 5级通关秘籍:用带参函数搞定那些绕来绕去的关卡

ICode竞赛Python 5级通关秘籍:用带参函数搞定那些绕来绕去的关卡 在ICode竞赛的Python 5级训练场中,许多关卡的设计都充满了挑战性。玩家常常需要控制多个角色(如Dev、Spaceship等)在复杂的地图中移动、转向、交互。面对这些看似杂…...

告别卡顿!用Mesh Shader在Unity里渲染百万级模型(附HLSL代码)

百万级模型流畅渲染实战:Unity中Mesh Shader的深度应用 当你在Unity中加载一个包含数十万面数的城市模型时,是否经历过帧率瞬间跌至个位数的绝望?传统渲染管线在面对复杂几何体时的力不从心,正是Mesh Shader技术要解决的核心痛点。…...

NanoPi M6硬件解析与嵌入式开发实践

1. NanoPi M6 硬件架构深度解析NanoPi M6 是一款基于 Rockchip RK3588S SoC 设计的单板计算机,其硬件配置在当前 SBC 领域堪称旗舰级。作为长期从事嵌入式开发的工程师,我认为这款板卡最值得关注的是其平衡的性能与扩展性设计。1.1 核心处理器性能剖析RK…...

CentOS7服务器根目录爆满别慌!手把手教你用LVM在线扩容(附fdisk/lsblk命令详解)

CentOS7服务器根目录爆满应急处理指南:LVM动态扩容实战解析 凌晨三点,服务器监控突然发出刺耳的警报声——根目录使用率突破95%!这种场景对于运维人员来说再熟悉不过。生产环境中的服务仍在运行,但可用空间正在以肉眼可见的速度减…...

SoC能耗估计协处理器设计与优化实践

1. SoC能耗估计协处理器设计背景与核心价值在移动设备和嵌入式系统领域,芯片级能耗管理已经成为决定产品竞争力的关键因素。随着5G、AIoT等技术的普及,现代SoC设计面临着一个根本性矛盾:一方面需要集成更多功能单元来满足性能需求&#xff0c…...

解决ClaudeCode访问不稳定问题通过Taotoken配置Anthropic兼容通道

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 解决ClaudeCode访问不稳定问题通过Taotoken配置Anthropic兼容通道 对于依赖Claude Code作为日常编程助手的开发者而言,…...

视频监督微调(SFT)提升多模态大模型时序理解能力

1. 项目背景与核心价值去年我在参与一个跨模态内容生成项目时,发现现有视觉大模型对视频时序信息的理解存在明显短板。当我们需要基于一段烹饪视频生成步骤说明时,模型往往只能识别出食材和工具,却无法准确描述"先放油后加菜"这样的…...

STM32驱动BQ40Z50电量计:手把手教你读取电池电压、电流和剩余电量(附完整代码)

STM32驱动BQ40Z50电量计实战:从零搭建电池监测系统 在物联网和便携式设备爆发的时代,精确的电池管理已成为硬件开发的核心需求。BQ40Z50作为TI推出的高精度电量计芯片,凭借其专利的Impedance Track技术,能够准确测量锂离子电池的剩…...

模型驱动开发在嵌入式系统中的应用与实践

1. 模型驱动开发的核心价值与挑战在嵌入式系统开发领域,传统代码优先(Code-First)方法存在一个根本性矛盾:系统行为的正确性验证往往被推迟到集成测试阶段,而此时发现的设计缺陷修复成本呈指数级增长。我曾参与过一个工…...

XUnity.AutoTranslator:3分钟安装,让外文游戏瞬间变中文的终极神器

XUnity.AutoTranslator:3分钟安装,让外文游戏瞬间变中文的终极神器 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 还在为日文、英文游戏看不懂而烦恼吗?XUnity.AutoTr…...

npm install报错errno -4077?可能是你的项目路径或Node版本埋的坑

npm install报错errno -4077?可能是你的项目路径或Node版本埋的坑 接手老项目或升级开发环境时,npm install突然抛出errno -4077错误,往往让开发者一头雾水。这个看似权限问题的错误代码,背后可能隐藏着项目路径、Node版本兼容性、…...

二值统计-原理和应用场景

二值统计-原理和应用场景 二值统计概述 二值统计通常涉及到将数据分为两个类别或状态,比如成功与失败、是与非等,并对这些类别进行计数和分析。 这种统计方法在处理二分类问题时非常常见,比如在质量控制、用户行为分析等领域。 二值统计的4大…...

用Python和face3d库,5分钟搞定3DMM人脸重建(附完整代码)

用Python和face3d库5分钟实现3D人脸重建实战指南 在咖啡馆里,一位游戏开发者正对着笔记本电脑屏幕上的平面人像皱眉——他需要为角色创建3D模型,但传统建模软件需要数小时手工调整。此时,3D Morphable Model(3DMM)技术…...

使用gradient-cursor库为网页添加渐变动态光标效果

1. 项目概述:为你的网页注入灵魂光标 在网页设计的细节里,鼠标光标常常是被忽视的一环。默认的白色箭头或小手图标,虽然功能明确,但千篇一律,缺乏个性。你是否想过,当用户在你的个人作品集、创意网站或交互…...

基于LLM的AI安全助手:hackingBuddyGPT框架设计与实战

1. 项目概述:当安全研究员拥有一个AI助手如果你是一名网络安全从业者,或者对渗透测试、红队攻防感兴趣,那么你一定对日常工作中那些重复、繁琐但又至关重要的任务感到熟悉:一遍遍地扫描端口,手动测试各种漏洞利用链&am…...

SAP销售模块实战:三种业务场景下,如何精准抓取销售成本与收入数据(附SQL思路)

SAP销售模块实战:三种业务场景下精准抓取销售成本与收入数据的SQL实现 销售毛利分析是企业经营决策的核心依据,但在SAP系统中直接获取这些数据却充满挑战。作为经历过多个行业项目的实施顾问,我发现不同成本结转方式会导致数据分布在完全不同…...

基于MCP协议的Google AI工具集:简化AI智能体多模态能力集成

1. 项目概述:一个为AI智能体赋能的Google AI工具集 最近在折腾AI智能体(Agent)的开发,发现一个痛点:想让智能体具备“看”和“听”的能力,比如翻译一段外文、识别图片里的文字、或者分析一段话的情绪&…...

Cursor编辑器RTL文本修复:解决阿拉伯语等从右向左语言输入问题

1. 项目概述:一个为开发者解决RTL语言输入问题的Cursor插件如果你是一位使用阿拉伯语、希伯来语等从右向左(RTL)书写语言的开发者,并且正在使用Cursor——这款基于AI的智能代码编辑器,那么你很可能遇到过这样的困扰&am…...

打造高效终端工作流:multicli模块化命令行工具实战指南

1. 项目概述:一个终端里的“瑞士军刀”如果你和我一样,每天大部分时间都泡在终端里,那你肯定也经历过这种场景:想快速查看一下某个目录的Git状态,得敲git status;想看看当前目录的磁盘占用,得敲…...

告别‘炼丹炉’:用ncnn+ONNX把PyTorch模型轻松‘瘦身’部署到边缘设备

从PyTorch到边缘设备:ncnnONNX轻量化部署实战指南 边缘计算时代的模型部署挑战 当我们将训练好的PyTorch模型部署到边缘设备时,常常会遇到这样的困境:在开发机上运行流畅的模型,到了树莓派或移动设备上却变得异常缓慢&#xff0…...