eve 的 MCP Skills 通道:技能参考文件如何做到「字节级精确」发布——以 kennel-handbook 为例
人工智能AI AgentAgent 框架后端工具调用【免费下载链接】eveThe Open Framework for Building Agents项目地址https://gitcode.com/gh_mirrors/eve28/eve点击查看免费下载在 eve 中一个 Agent 的skills/目录不仅仅是给 Agent 自己读取的说明文档——通过 MCP 通道的skills: true配置技能包会被发布为符合 SEP-2640 规范的 MCP Skills外部客户端可以像访问 MCP 资源一样读取技能内的每一个文件。本文以仓库中的端到端夹具kennel-handbookMaple Street 犬舍前台手册为线索结合其源码与测试深入讲解 eve 如何以skill://URI 发布技能文件、为什么它能做到「byte for byte」逐字节精确地服务二进制与非 UTF-8 文件以及发布时的校验边界与实现细节。读完本文你将掌握 eve MCP Skills 通道的配置方式、技能文件的服务语义以及如何用端到端测试验证其字节级一致性。一、先看主角kennel-handbook 技能包本文关联的核心文档是 e2e/fixtures/agent-mcp/agent/skills/kennel-handbook/SKILL.md全文如下--- name: kennel-handbook description: Front-desk handbook for the Maple Street kennel, with its reference files. --- # Kennel handbook The files under references/ and assets/ are served byte for byte.这份文档很短但它点出了 eve MCP Skills 通道的核心承诺技能包references/与assets/目录下的文件会被「逐字节精确」地服务served byte for byte。这句话并不是营销话术而是有完整实现与自动化测试背书的行为契约——这正是本文要展开的技术主题。技能包的实际目录结构位于 e2e/fixtures/agent-mcp/agent/skills/kennel-handbook/skills/kennel-handbook/ ├── SKILL.md # 技能入口文档frontmatter 正文 ├── assets/ │ └── logo.png # 二进制占位图1x1 PNG └── references/ ├── empty.md # 空文件 └── latin1.md # 非 UTF-8 编码的 MarkdownLatin-1 编码注意这三个被服务文件的刻意选择一个PNG 二进制、一个空文件、一个非 UTF-8 文本——它们分别对应测试注释中所说的「a bundler or asset store would alter if it handled them by name」如果按文件名去处理打包器或资源存储很可能会改变它们的形态。eve 的选择是不做任何编码转换、不重编码、不规范化直接以原始字节服务。二、SKILL.md 的入口格式规范技能包以SKILL.md为唯一入口文件其 frontmatter 必须满足「Agent Skills 格式」。从实现看这套规则定义在 packages/eve/src/internal/mcp/skills.ts 的conforming()检查中name164 个字符且必须匹配^[a-z0-9](?:-[a-z0-9])*$即仅允许小写字母、数字与内部单个连字符如kennel-handbookdescription去除首尾空白后不能为空长度不超过 1024 字符SKILL.md必须能被解析为 UTF-8 文本且带有符合上述规则的 frontmatter。kennel-handbook的 frontmatter 恰好命中了最优路径当SKILL.md的 frontmatter 已携带与技能名一致的name和字符串description时入口文档被原样服务verbatim。如果 frontmatter 缺失或与目录名不一致例如扁平技能或模块技能物化出来的SKILL.md没有 frontmatter实现会用 JSON 形式重新渲染 frontmatter 注入name与description此时服务出去的文档字节就与作者文件不同了——所以「byte for byte」的承诺严格说是针对references/、assets/等普通文件以及 frontmatter 合规的入口文档本身。三、通过 MCP 发布技能mcpChannel 的 skills 开关技能要能被外部读取前提是 Agent 的 MCP 通道开启了 skills 发布能力。eve 的mcpChannel见 packages/eve/src/public/channels/mcp.ts把 Agent 发布为一个无状态的 Streamable HTTP MCP Server其关键配置项包括配置项默认值说明auth必填复用 eve 的 route-auth 策略可用none()显式声明公开访问route/eve/v1/mcpMCP 路由路径agenttrue是否服务agent_*持久化任务工具toolsfalse是否发布 Agent 的可调用工具每个tools/call以路由认证调用者的身份执行skillsfalse是否按 SEP-2640 把 Agent 技能发布为skill://下的 skillsskills/list、skills/get及resources/*方法trustedForwarders无允许哪些经过验证的转发者如另一个 eve Agent 的forwardPrincipal连接以它指定的用户身份运行已发布工具当agent、tools、skills全为false时mcpChannel会直接抛错——通道至少要发布一类内容。夹具中的 e2e/fixtures/agent-mcp/agent/channels/mcp.ts 展示了完整配置import { mcpChannel } from eve/channels/mcp; import { SERVICE_ID, SERVICE_TOKEN } from ../../fixture; export default mcpChannel({ auth: (request) request.headers.get(authorization) Bearer ${SERVICE_TOKEN} ? { attributes: {}, authenticator: e2e-fixture, principalId: SERVICE_ID, principalType: service, } : null, skills: true, tools: true, // 仅此服务loopback 连接可以转发用户的身份 trustedForwarders: (forwarder) forwarder.authenticator e2e-fixture forwarder.principalId SERVICE_ID, });四、skill:// URI 与资源方法技能被发布为一组 MCP 资源统一使用skill://协议前缀。URI 形如skill://skill[/path]例如skill://kennel-handbook/SKILL.md、skill://kennel-handbook/assets/logo.png。底层服务方法是createMcpSkillsFeature实现于 packages/eve/src/internal/mcp/skills.ts它按 SEP-2640 注册了六个方法skills/list列出所有被服务的技能及其入口 URI、frontmatter、资源清单含 digest 与 sizeskills/get按skill://name/SKILL.md取单个技能的完整条目resources/list以扁平资源形式列出所有技能入口resources/templates/list固定返回空模板列表技能资源不使用 URI 模板resources/directory/read按目录读取技能内的子资源assets/、references/等空目录也会被列出resources/read读取单个文件的实际内容。URI 的解析是严格模式parseSkillUri()会拒绝 query/fragment、空白字符、反斜杠、空路径段//与末尾/、.和..段包括被百分号解码出来的、百分号编码的/、\或 NUL以及任何畸形的百分号编码。所有列表方法也不接受分页游标任何cursor都会以 InvalidParams 拒绝因为列表总是整体返回。值得注意的是该特性直接挂载在底层 server 的 request handler 上而不是通过McpServer.registerResource注册——后者的resources/read会先用new URL()规范化 URI会把..解析掉这正是实现方想要规避的行为。五、「byte for byte」的实现机制5.1 text 与 blob 的自动判别resources/read返回的contents[0]有两种形态文本形态{ uri, mimeType, text }二进制形态{ uri, mimeType, blob }blob 为 base64 编码。判别逻辑在toServedFile()/decodeText()packages/eve/src/internal/mcp/skills.ts/** Decodes UTF-8 text without NUL bytes; returns undefined for anything else. */ function decodeText(bytes: Uint8Array): string | undefined { if (bytes.includes(0)) return undefined; try { return new TextDecoder(utf-8, { fatal: true, ignoreBOM: true }).decode(bytes); } catch { return undefined; } }即含 NUL 字节或无法以 UTF-8严格模式解码的文件一律按 blob 以 base64 原样交付。这也解释了夹具为什么专门放了一个 Latin-1 编码的latin1.md——它会触发 fatal 解码失败从而验证二进制路径empty.md空文件与logo.pngPNG 二进制则分别覆盖边界与真实二进制场景。由于服务端始终基于原始字节构造响应MCP 传输层不做任何编码转换客户端拿到的就与作者文件逐字节一致。5.2 MIME 类型推断servedMimeType()按扩展名查表packages/eve/src/internal/mcp/skills.ts 内置了约 22 种常见类型例如md → text/markdown、png → image/png、txt → text/plain、json → application/json、ts → text/typescript。未知扩展名时退回到文本文件 →text/plain二进制 →application/octet-stream。5.3 digest 与快照缓存每个被服务的文件都会计算sha256:hexdigest随资源条目一起通过skills/list/skills/get暴露供 MCP 客户端做变更检测。快照以技能描述数组describe()的输出为键缓存在WeakMap中生产环境一次进程生命周期只构建一次eve dev下每次重新编译后失效重建。内存中只常驻SKILL.md其余文件在每次resources/read时重新读取所以缓存快照只占元数据开销。六、服务边界整包服务或完全不服务技能采用「全有或全无」策略一个技能要么被完整发布到所有方法中要么从所有方法中缺席。servedPaths()与snapshotSkill()会在发布前对技能做一轮完整体检任何一条不满足都会导致整个技能不发布并记录一条 warn 日志例如mcpChannel does not serve the skill ...校验项限制技能名与每个文件/目录路径必须是合法的skill://段见第四节 URI 规则文件数量最多 512 个文件MCP_SKILL_MAX_RESOURCES单文件大小不超过 512 KiBMAX_SKILL_FILE_BYTES定义于 packages/eve/src/channel/skill-files.ts总大小全部文件合计不超过 16 MiBMCP_SKILL_MAX_TOTAL_BYTES入口文件必须恰好有一个顶层入口SKILL.md大小写不敏感skill.md也可被发现统一以SKILL.md服务不允许出现多个可读性每个文件都能成功读取入口格式SKILL.md为 UTF-8 文本且 frontmatter 符合 Agent Skills 格式值得一提的还有两点其一大小限制在列出时和实际读取后会被检查两次——因为文件可能在列出与读取之间发生变化且重写后的SKILL.md可能增长其二单个文件读取失败SkillReadError视为整包不发布但若是瞬时性错误如磁盘/资产读取失败则会让快照失效并在下一次请求时重试避免永久缓存一次失败的构建。七、端到端验证如何证明「逐字节一致」夹具自带的评测 e2e/fixtures/agent-mcp/evals/skill-files.eval.ts 正是为验证这份承诺而写的它用 Node 的readFile读出作者侧文件再以标准 MCP HTTP 客户端语义向/eve/v1/mcp发起resources/read最后断言两者hex 编码完全相等const FILES [assets/logo.png, references/empty.md, references/latin1.md]; // ... const uri skill://${SKILL}/${path}; const response await t.target.fetch(MCP_PATH, { body: JSON.stringify({ id: 1, jsonrpc: 2.0, method: resources/read, params: { uri, _meta: {...} } }), headers: { accept: application/json, text/event-stream, authorization: Bearer ${SERVICE_TOKEN}, content-type: application/json, mcp-method: resources/read, mcp-name: uri, mcp-protocol-version: PROTOCOL_VERSION, // 2026-07-28 }, method: POST, }); // blob(base64) 或 text 都被还原为 Buffer再与作者文件做 hex 比对 await t.require({ path, bytes: served.toString(hex) }, equals({ path, bytes: authored.toString(hex) }));响应中的blob以 base64 还原、text以 UTF-8 还原两条路径都覆盖。这条评测的 description 写得很直白Alices front-desk client reads the kennel handbooks files over MCP and gets them byte for byte, whatever their encoding.——不管编码如何逐字节一致。八、闭环演示loopback 连接与技能配套能力这个夹具不止验证文件服务还演示了「Agent 通过自己的 MCP 通道调用自己的工具」的闭环连接 e2e/fixtures/agent-mcp/agent/connections/loopback.ts 使用defineDynamic在session.started时按会话解析部署 URL创建defineMcpClientConnection并携带forwardPrincipal: true与 Bearer token 回调自己的通道。配套评测e2e/fixtures/agent-mcp/evals/call.eval.ts验证了当用户 Alice 通过x-eve-fixture-user: alice头发起请求时工具loopback__whoami能看到principalId: alice、principalType: user以及forwardedBy: SERVICE_ID——即身份被转发而不是以服务身份代执行。另一个边界用例是 e2e/fixtures/agent-mcp/evals/approval.eval.ts需要人工审批的工具publish_notice.ts用always()策略要求每次发帖前询问通过 MCP 通道调用时会以工具失败的形式返回「needs a persons approval, which this MCP channel cannot ask for」的错误且工具永远不会真正执行calledTool(..., { count: 0 })。这体现了 MCP 通道在人工审批HITL能力边界上的明确语义。九、总结从一份只有三行的SKILL.md出发我们看到 eve 的 MCP Skills 通道提供了一套完整、可验证的技能文件服务契约入口规范SKILL.md的 frontmatter 必须携带合规的name与description否则技能整包不发布发布语义mcpChannel({ skills: true })把技能包按 SEP-2640 发布为skill://资源支持skills/list、skills/get、resources/*全系列方法字节级保真UTF-8 文本走text字段二进制与非 UTF-8 文件走 base64blob字段服务端始终基于原始字节响应不做任何转换严格边界512 文件 / 512 KiB 单文件 / 16 MiB 总量上限、安全 URI 段校验、整包全有或全无可验证性端到端评测用 hex 逐字节比对作者文件与服务内容把「byte for byte」从文档承诺变成了可回归的自动化断言。如果你在自己的 eve Agent 中需要让外部 MCP 客户端读取技能附带的手册、模板、图片等参考资产这套机制就是开箱即用的答案把文件放进技能包的references/或assets/开启通道的skills开关剩下的字节级保真由 eve 负责。赞分享人工智能AI AgentAgent 框架后端工具调用【免费下载链接】eveThe Open Framework for Building Agents项目地址https://gitcode.com/gh_mirrors/eve28/eve点击查看免费下载相关推荐用 mcp-use 为 MCP Server 编写 Agent Skills以 refunds 退款技能为例的完整实战解析用 mcp use 为 MCP Server 编写 Agent Skills以 refunds 退款技能为例的完整实战解析 导读本文以 mcp use 仓库后端MCP 服务MCP ClientsAI Agent人工智能gentle-ai review authority 发布版 fixture 溯源与字节级校验以 v1.49.0 ordinary 4R 为例gentle ai review authority 发布版 fixture 溯源与字节级校验以 v1.49.0 ordinary 4R 为例 GentleWindows 与 Office 免费激活完整教程MAS v3.12 四种激活方式一篇讲清Windows 与 Office 免费激活完整教程MAS v3.12 四种激活方式一篇讲清 想搞定 Windows 激活和 Office 激活又不想花钱买授操作系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考