MCPixy:零配置构建LLM工具网关,YAML定义CLI/HTTP/Web工具
1. 项目概述零配置构建你的LLM工具网关如果你正在使用 Cursor、Claude Desktop 这类集成了 MCP 协议的 AI 编程助手并且厌倦了为了连接一个简单的系统命令或 API 而去编写繁琐的 JavaScript 或 Python 服务器代码那么 MCPixy 的出现可能会让你眼前一亮。简单来说MCPixy 是一个“零配置”的 MCP 服务器构建器它的核心价值在于让你能够通过编写 YAML 配置文件在几分钟内就将任何命令行工具、HTTP API 或网页数据安全地暴露给你的大语言模型使用整个过程无需编写一行服务器逻辑代码。MCP 全称是 Model Context Protocol你可以把它理解成 AI 助手如 Cursor 中的 AI 伙伴与外部世界你的文件系统、数据库、API 等进行安全、标准化通信的桥梁。传统的 MCP 服务器开发需要你熟悉协议规范、处理 WebSocket 连接、定义工具 Schema门槛不低。而 MCPixy 则把这个过程极度简化了你只需要描述“工具是什么”和“工具怎么用”剩下的协议封装、服务启动、安全校验全部由 MCPixy 自动完成。这对于需要快速为 LLM 扩展能力的开发者、运维工程师甚至是技术背景的产品经理来说都是一个效率利器。接下来我将从一个实践者的角度带你深入拆解 MCPixy 的设计思路、核心功能并分享从部署到实战再到安全加固的完整经验。2. 核心设计思路与架构解析2.1 为什么是“零配置”“零配置”这个词在开源项目里很常见但 MCPixy 的零配置有其特定的含义。这里的“零”并非指完全不需要任何配置而是指无需进行传统的“服务器编程”。传统的 MCP 服务器开发流程是新建一个项目 - 安装 SDK - 编写工具函数 - 编写协议适配代码 - 处理启动和连接。MCPixy 将后三步全部固化为了一个通用的、用 Rust 编写的高性能网关服务。这个网关服务一旦启动就成为了一个标准的 MCP 服务器端点。你的工作从“编写程序”变成了“编写声明”。你通过 YAML 文件声明一个工具的输入参数、执行方式CLI、HTTP 等和输出格式MCPixy 负责在运行时解析这个声明动态地将它适配成 MCP 协议规定的工具调用格式。这种设计哲学类似于“基础设施即代码”只不过这里变成了“工具即配置”。它极大地降低了使用门槛让关注点完全集中在工具本身的功能定义上而不是繁琐的通信协议实现上。2.2 三大工具类型的设计考量MCPixy 抽象出的三种工具类型CLI, HTTP, Web Scraping覆盖了绝大多数 LLM 需要与外部交互的场景这个设计非常精准。CLI 工具类型是针对系统交互和脚本执行的。想象一下你想让 AI 帮你查看当前目录的 Git 状态、运行一个构建脚本、或者查询 Docker 容器列表。在传统方式下你需要为每个命令写一个包装函数。而在 MCPixy 中你只需要在 YAML 里定义命令模板和参数映射。这种设计的安全边界很清晰工具的执行权限完全遵循启动 MCPixy 进程的系统用户权限并且可以通过配置限制可执行的命令范围。HTTP 工具类型是针对现代应用最常见的交互方式——RESTful API。无论是调用内部管理系统、查询天气、还是发送消息到 Slack本质上都是一次 HTTP 请求。MCPixy 的 HTTP 工具类型支持配置方法、URL、Headers、Query 参数和 Body并且支持 Mustache 风格的模板语法{{input.param}}来动态注入 LLM 提供的参数。这相当于一个可编程的 HTTP 客户端让 LLM 能够安全、规范地调用任何授权过的 API。Web Scraping 工具类型则是一个更高级的抽象。它本质上也是 HTTP 请求但目标是从返回的 HTML 中提取结构化数据。通过配置 CSS 选择器你可以告诉 MCPixy“访问这个网址然后找到所有 class 为 ‘product-name’ 的 span 标签把它们的文本内容提取出来以 JSON 数组的形式返回给 AI。” 这避免了让 LLM 去直接解析和理解杂乱的 HTML而是由 MCPixy 先完成数据清洗和结构化再将干净的数据喂给 LLM大大提升了信息获取的准确性和效率。2.3 安全与信任模型剖析对于一个允许执行系统命令和发起网络请求的网关安全是重中之重。MCPixy 的安全设计是分层的。最基础的一层是进程权限隔离。MCPixy 服务本身以某个系统用户身份运行它执行的所有 CLI 命令都继承此用户的权限。这意味着在部署时你需要慎重考虑用哪个用户来运行 MCPixy通常建议使用一个权限受限的专用用户。核心的安全机制是数字签名。这是 MCPixy 一个非常巧妙的设计。工具定义文件YAML本身是明文可能存在被篡改的风险例如有人将ls -la偷偷改成了rm -rf /。为了解决这个问题MCPixy 引入了 Ed25519 非对称加密签名。工具开发者或管理员使用私钥对工具定义文件或其中某个工具进行签名生成一个签名文件。MCPixy 服务在加载工具时会用对应的公钥验证签名。只有签名验证通过的工具才会被加载和执行。这意味着即使工具配置文件被意外修改也会因为签名不匹配而被网关拒绝从根本上防止了工具被恶意篡改。在此之上是网络层认证即 JWT 认证。当 MCPixy 以 JWT 模式运行时客户端如 Cursor在连接时必须提供一个有效的 JWT Token。这确保了只有持有合法 Token 的客户端才能访问网关适用于多用户或需要区分调用来源的场景。JWT 的密钥HS256或密钥对RS256由管理员配置实现了调用方的身份认证。最后审计日志记录了每一次工具调用的详细信息谁调的JWT 身份、什么时候调的、调了什么工具、输入参数是什么、执行成功与否、耗时多久。这为事后的安全审计、故障排查和用量分析提供了完整的数据支持。3. 从零开始的完整实战部署3.1 环境准备与编译安装MCPixy 使用 Rust 编写因此第一步是安装 Rust 工具链。我推荐使用rustup这是 Rust 官方的工具链管理器。# 安装 rustup 和 Rust 稳定版工具链 curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh source $HOME/.cargo/env rustup default stable安装完成后使用rustc --version确认版本在 1.70 以上。接下来获取 MCPixy 源码并编译。这里有个细节需要注意官方 README 里的cd命令指向了mcpgw这可能是个笔误或旧目录名。根据仓库结构正确的目录名就是mcpixy。# 克隆仓库 git clone https://github.com/jondot/mcpixy.git cd mcpixy # 进行发布模式编译优化执行速度 cargo build --release编译过程可能需要几分钟取决于你的网络和机器性能。编译完成后可执行文件位于target/release/mcpixy。为了方便使用我习惯将它链接到系统路径# 将编译好的二进制文件复制到用户本地 bin 目录假设 ~/.local/bin 已在 PATH 中 cp target/release/mcpixy ~/.local/bin/ # 或者使用 cargo install 直接安装 cargo install --path .3.2 初始化配置与密钥生成安装完成后不要急着启动服务。第一步应该是使用bootstrap命令初始化工作环境。mcpixy bootstrap这个命令会做以下几件关键事情创建配置目录在~/.mcpixy/下生成默认的目录结构。生成默认配置创建~/.mcpixy/gateway.toml配置文件里面包含了服务器端口、日志级别、认证模式等基础设置。生成密钥对创建一对 Ed25519 密钥private_key.pem和public_key.pem用于后续的工具签名和验证。请务必妥善保管private_key.pem它相当于你的“工具发布根证书。创建示例工具文件在~/.mcpixy/tools/目录下生成一个sample_tools.yaml文件里面预置了几个不同工具类型的示例是你学习工具定义语法的最佳起点。执行完后可以查看一下生成的文件结构tree ~/.mcpixy -a你应该能看到类似如下的结构~/.mcpixy/ ├── gateway.toml ├── private_key.pem ├── public_key.pem └── tools/ └── sample_tools.yaml3.3 定义你的第一个工具一个天气查询接口让我们抛开简单的示例来定义一个有点实用价值的工具通过一个公共天气 API 查询城市天气。我们将使用 HTTP 工具类型。首先编辑~/.mcpixy/tools/weather_tools.yaml你可以新建这个文件tools: - id: get_current_weather type: http name: 获取当前天气 description: 根据城市名称查询当前的天气状况包括温度、天气描述和湿度。 method: GET # 这里使用一个免费的天气API示例请注意这类API可能有调用限制 url: https://api.openweathermap.org/data/2.5/weather headers: User-Agent: MCPixy-Weather-Client/1.0 query: q: {{input.city}} appid: YOUR_API_KEY_HERE # 你需要在对应网站注册并替换为真实的API Key units: metric # 使用摄氏度 lang: zh_cn input_schema: type: object properties: city: type: string description: 城市名称例如Beijing, Shanghai, London。建议使用英文城市名。 required: [city] output_schema: type: object properties: location: type: string description: 查询的城市和地区 temperature: type: number description: 当前温度单位摄氏度 description: type: string description: 天气状况描述如‘晴朗’、‘多云’ humidity: type: number description: 湿度百分比 required: [location, temperature, description, humidity]这个 YAML 片段定义了一个完整的工具id: 工具的唯一标识符在签名和调用时使用。type: 指定为http。name和description: 这些信息会暴露给 LLM帮助它理解工具用途。描述写得越清晰LLM 调用得越准确。method和url: 定义了 HTTP 请求的基本要素。query: 定义了 URL 查询参数。{{input.city}}是一个模板变量它会被 LLM 调用时提供的city参数值替换。input_schema: 使用 JSON Schema 严格定义了工具需要的输入参数。这是 MCP 协议的要求也是 LLM 能正确调用工具的关键。它告诉 LLM“调用我这个工具时你必须提供一个叫city的字符串参数。”output_schema: 同样使用 JSON Schema 定义了工具返回的数据结构。这有助于 LLM 理解返回结果并进行后续的推理或回答组织。注意在实际使用公共 API 时务必将YOUR_API_KEY_HERE替换为你自己申请的密钥并遵守该 API 的服务条款和调用频率限制。将 API Key 直接写在 YAML 配置里虽然方便但在团队协作或公开仓库中存在泄露风险。更安全的做法是通过环境变量注入这需要你根据 MCPixy 的配置能力如支持模板变量从环境读取或自行编写一个简单的包装脚本CLI 类型来实现。3.4 签名工具并启动服务工具定义好后在投入生产前必须对其进行签名以启用安全验证。# 为 weather_tools.yaml 文件中的所有工具签名 mcpixy sign-tool --file ~/.mcpixy/tools/weather_tools.yaml # 你也可以只为单个工具签名如果文件中有多个工具 # mcpixy sign-tool --file ~/.mcpixy/tools/weather_tools.yaml --tool-id get_current_weather签名命令会读取~/.mcpixy/private_key.pem对工具文件内容进行计算并在同目录下生成一个.sig签名文件例如weather_tools.yaml.sig。现在可以启动 MCPixy 服务了。默认情况下MCPixy 只加载已签名的工具。为了测试我们可以先以允许未签名工具的模式启动方便调试。# 在后台启动服务允许未签名工具并指定日志级别为 debug mcpixy --allow-unsigned --log-level debug 服务默认监听3033端口。你可以通过访问http://localhost:3033/ui来打开内置的 Web UI。这个 UI 非常有用你可以在这里看到所有已加载的工具列表甚至可以直接在界面上测试工具调用而无需通过 Cursor。3.5 在 Cursor IDE 中完成配置这是最后一步也是让工具真正能被 AI 使用的关键。我们需要在 Cursor 的 MCP 配置中告诉它去哪里找我们的 MCPixy 服务器。找到你的 Cursor MCP 配置文件。通常位于macOS/Linux:~/.cursor/mcp.jsonWindows:%USERPROFILE%\.cursor\mcp.json如果文件不存在就创建一个。然后添加以下配置{ mcpServers: { mcpixy-weather: { command: mcpixy, args: [--allow-unsigned], // 初期调试用生产环境应移除并依赖签名 env: { MCPIXY_CONFIG_DIR: /home/your_username/.mcpixy // 可选显式指定配置目录 } } } }这里我们使用了command模式让 Cursor 直接启动mcpixy进程并与之通信。args里传递了--allow-unsigned以便调试。env可以设置环境变量确保 MCPixy 能找到正确的配置目录。配置保存后需要完全重启 Cursor IDE。重启后当你打开聊天界面你的 AI 助手就应该能“看到”并使用我们刚刚定义的“获取当前天气”工具了。你可以尝试对它说“请用工具帮我查一下伦敦的天气。”4. 高级配置与生产环境考量4.1 网关配置详解 (gateway.toml)bootstrap生成的gateway.toml是主配置文件。让我们深入看一下关键部分[server] # 服务绑定的地址和端口 address 127.0.0.1 port 3033 # 日志级别error, warn, info, debug, trace log_level info [gateway] # 工具配置文件所在的目录支持多个目录 tools_dirs [~/.mcpixy/tools] # 是否递归搜索子目录 recursive true # 允许加载未签名的工具吗生产环境务必设为 false allow_unsigned false [auth] # 认证模式: none 或 jwt mode none # 当 mode jwt 时以下配置生效 # algorithm HS256 # secret your-256-bit-secret # 用于 HS256 算法的密钥 # public_key_path path/to/public_key.pem # 用于 RS256 算法的公钥路径 [audit] # 审计日志是否启用 enabled true # 审计日志文件路径 file_path ~/.mcpixy/audit.log生产环境调整建议地址与端口如果希望从同网络的其他机器访问可将address改为0.0.0.0。同时考虑使用反向代理如 Nginx将服务暴露到公网并配置 HTTPS。日志级别生产环境建议设为info或warn避免debug日志产生过多 I/O。安全开关必须将allow_unsigned设置为false强制所有工具必须经过签名验证。认证模式如果服务需要暴露在非完全可信的网络环境应将auth.mode设为jwt并配置强密钥。4.2 启用 JWT 认证启用 JWT 认证后客户端连接时必须提供有效的 Token。配置如下[auth] mode jwt algorithm HS256 # 也可以使用 RS256 secret a-very-strong-and-long-secret-key-at-least-32-bytes # HS256 的密钥然后你需要生成一个 JWT Token。可以使用在线工具或者用你熟悉的编程语言生成。以 Node.js 为例const jwt require(jsonwebtoken); const secret a-very-strong-and-long-secret-key-at-least-32-bytes; const payload { sub: cursor-ide, // 主题通常是客户端标识 name: My Cursor IDE, iat: Math.floor(Date.now() / 1000), // 签发时间 exp: Math.floor(Date.now() / 1000) (60 * 60 * 24), // 24小时后过期 }; const token jwt.sign(payload, secret, { algorithm: HS256 }); console.log(token);最后更新 Cursor 的mcp.json在连接时带上这个 Token{ mcpServers: { mcpixy-secure: { command: mcpixy, args: [], env: {}, headers: { Authorization: Bearer YOUR_GENERATED_JWT_TOKEN_HERE } } } }4.3 工具定义的进阶技巧1. 复杂的 CLI 工具与参数处理CLI 工具的参数可以通过模板灵活构造。例如一个查找文件的工具tools: - id: find_files type: cli name: “查找文件” description: “在指定目录下根据名称模式查找文件。” command: “find” args: - “{{input.path}}” - “-name” - “{{input.pattern}}” - “-type” - “f” # 设置超时防止命令长时间挂起 timeout_seconds: 30 input_schema: type: object properties: path: type: string description: “搜索的起始路径例如 ‘.’ 或 ‘/home/user’” default: “.” pattern: type: string description: “文件名匹配模式例如 ‘*.log’ 或 ‘project-*’” required: [pattern]2. HTTP 工具的请求体与复杂 Header对于 POST/PUT 请求可能需要发送 JSON 或 Form 数据。tools: - id: create_todo type: http name: “创建待办事项” method: POST url: “https://api.example.com/todos” headers: Content-Type: “application/json” Authorization: “Bearer {{env.API_TOKEN}}” # 可以从环境变量读取敏感信息 body: | { “title”: “{{input.title}}”, “description”: “{{input.description}}”, “dueDate”: “{{input.due_date}}” } input_schema: # ... 定义 title, description, due_date 属性3. Web Scraping 的链式提取有时需要从页面中提取多个相关字段。tools: - id: scrape_news type: web_scraping name: “抓取新闻标题和链接” url: “{{input.news_url}}” selectors: items: “div.article-list article” # 首先选中所有文章元素 fields: # 然后在每个 item 中提取字段 title: “h2 a | text” # 提取 h2 标签内 a 标签的文本 link: “h2 a | attr(href)” # 提取 href 属性 summary: “p.summary | text” input_schema: # ... 定义 news_url 属性这种配置会让 MCPixy 返回一个 JSON 数组每个元素是包含title,link,summary的对象。5. 故障排查与性能优化经验在实际使用中你可能会遇到各种问题。以下是我总结的一些常见场景和解决思路。5.1 工具加载失败症状服务启动正常但 Web UI 中看不到工具或者 Cursor AI 提示找不到工具。检查点 1配置文件位置与权限确保工具 YAML 文件放在gateway.toml中tools_dirs配置的目录下。检查文件读权限。检查点 2签名验证如果allow_unsigned是false确保每个工具 YAML 文件都有对应的.sig签名文件并且是用当前配置目录下的私钥签名的。可以手动运行mcpixy verify-tool --file your_tools.yaml来验证。检查点 3YAML 语法YAML 对缩进非常敏感。使用在线的 YAML 校验器或yamllint工具检查文件语法是否正确。检查点 4日志信息以debug级别启动服务 (mcpixy --log-level debug)查看控制台输出通常会有加载工具成功或失败的详细原因。5.2 Cursor 无法连接 MCPixy 服务器症状Cursor 重启后AI 助手没有获得新工具或者提示连接错误。检查点 1MCPixy 进程是否在运行执行ps aux | grep mcpixy或查看端口占用lsof -i:3033。检查点 2Cursor 配置是否正确检查~/.cursor/mcp.json格式是否为合法 JSON。确认command路径是否正确如果mcpixy不在系统 PATH 中需使用绝对路径。检查点 3认证问题如果启用了 JWT检查 Token 是否过期以及mcp.json中的headers配置格式是否正确。检查点 4Cursor 版本确保你使用的是支持 MCP 的 Cursor 版本。有时需要更新到最新版。5.3 工具执行超时或返回错误症状AI 调用工具后长时间无响应或返回非预期的错误信息。检查点 1CLI 工具超时检查timeout_seconds配置是否过短。对于执行时间可能较长的命令如大数据量查找、编译适当调大超时时间。检查点 2网络问题HTTP/Web Scraping 工具检查目标 URL 是否可达API 密钥是否有效网络是否有防火墙限制。可以在服务器上直接用curl命令测试工具定义的 URL 和参数。检查点 3权限问题CLI 工具检查运行 MCPixy 的用户是否有权限执行你定义的命令。例如某些系统命令可能需要sudo权限。检查点 4输入参数格式通过 Web UI 手动测试工具输入与 AI 调用时类似的参数对比结果。确保input_schema的定义与实际工具处理逻辑匹配。5.4 性能优化建议工具分组与懒加载不要把所有工具都定义在一个巨大的 YAML 文件里。按功能或团队拆分成多个小文件。MCPixy 启动时会加载所有已签名的工具文件越大启动越慢。拆分文件便于管理也利于按需加载虽然当前版本似乎是全量加载。善用缓存对于 HTTP 或 Web Scraping 工具如果数据更新不频繁可以考虑在工具逻辑外部例如使用一个 cron 任务定期抓取并写入本地文件然后让 MCPixy 读取本地文件或未来在工具定义中增加缓存层来减少对外部服务的频繁调用提升响应速度并避免触发 API 限流。监控与日志务必启用审计日志 (audit.enabled true)。定期检查audit.log可以分析工具使用频率、识别性能瓶颈通过执行耗时、以及发现异常调用模式。资源限制在操作系统层面对运行 MCPixy 的进程设置资源限制如使用ulimit或 systemd 的LimitCPU,LimitMEMORY防止某个失控的工具调用如一个死循环脚本拖垮整个服务。5.5 一个真实的踩坑记录环境变量与路径问题我曾经定义过一个工具用来调用一个位于/opt/scripts/下的自定义 Python 脚本。在 YAML 中我直接写了command: “python3”和args: [“/opt/scripts/my_tool.py”, “{{input.param}}”]。在测试时通过 Web UI 手动调用一切正常。但当 AI 通过 Cursor 调用时却总是失败日志显示python3: command not found。问题根源Cursor 启动 MCPixy 时继承的环境变量可能与我在终端中手动启动时的环境变量不同。特别是PATH环境变量可能不包含/usr/local/bin或 Python3 的安装路径。解决方案使用绝对路径将命令改为/usr/bin/python3。在mcp.json中指定环境变量{ “mcpServers”: { “mcpixy”: { “command”: “/usr/local/bin/mcpixy”, “args”: [], “env”: { “PATH”: “/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin”, “PYTHONPATH”: “/opt/scripts” } } } }在工具定义中设置环境变量如果 MCPixy 支持command: “python3” args: [“my_tool.py”, “{{input.param}}”] env: PATH: “/usr/local/bin:/usr/bin:/bin” working_dir: “/opt/scripts”这个坑提醒我们在定义 CLI 工具时尤其是依赖特定环境或路径的工具要特别注意执行上下文的一致性。最稳妥的方式是在工具定义或服务启动配置中显式地指定绝对路径和所需的环境变量。