news 2026/9/16 11:04:51

MCP 官方 Registry 发布附加验证规则:server.json 在 registry 源码中的落地实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MCP 官方 Registry 发布附加验证规则:server.json 在 registry 源码中的落地实现

MCP 官方 Registry 发布附加验证规则:server.json 在 registry 源码中的落地实现

【免费下载链接】registryA community driven registry service for Model Context Protocol (MCP) servers.项目地址: https://gitcode.com/GitHub_Trending/registry43/registry

本文基于官方 Registry 的server.json附加要求文档,完整讲解发布到官方 MCP Registry(registry.modelcontextprotocol.io)时,在通用server.json规范之上额外施加的四类验证:命名空间鉴权、包归属验证、受限的 Registry Base URL 白名单,以及_meta命名空间限制。同时结合 registry 仓库源码,说明每条规则在验证器与鉴权处理函数中的具体实现位置与错误语义,帮助你在发布前预检问题、准确理解发布失败信息。

总览:官方 Registry 在通用规范之上做了什么

通用server.json格式(见 server.json 格式规范)定义了基础字段与结构校验,而官方 Registry 在此基础上追加了四类强制约束,目的是保证:

  • 命名空间鉴权(Namespace authentication):Server 只能发布到发布者实际拥有的命名空间之下;
  • 包归属验证(Package ownership verification):发布者必须能证明其确实拥有所引用的包,防止冒名;
  • 受限的 Registry Base URL:包必须来自受信任的公共 Registry,私有源与第三方镜像不被允许;
  • _meta命名空间限制_meta对象中仅publisher相关键的数据会被保留,其余键在发布时被静默丢弃。

从源码结构看,这四类约束分别落在不同模块:server 名称格式由 parseServerName 强制;包归属与 Base URL 白名单由internal/validators/registries/下的各验证器执行;_meta大小限制由 validatePublisherExtensions 执行;命名空间所有权证明由internal/api/handlers/v0/auth/下的各类鉴权端点完成。

命名空间鉴权:证明你拥有该命名空间

发布者必须证明其拥有对应命名空间。例如要发布到com.example/server,发布者必须证明其拥有example.com域名。

从源码可以确认 server 名称的硬性格式:name字段必须形如dns-namespace/name,恰好包含一个/,且匹配正则^[a-zA-Z0-9.-]+/[a-zA-Z0-9._-]+$(长度 3~200),定义在 ServerJSON 类型的 JSON Schema 标签与 parseServerName 中。命名空间部分只能以字母数字开头和结尾、中间可含点与连字符;name 部分额外允许下划线。格式不合法时,验证器会给出精确到"是 namespace 还是 name 部分非法"的错误提示。

Registry 提供了多种命名空间所有权证明途径,对应 鉴权实现目录 下的不同端点:

  • DNS 命名空间:通过解析域名 TXT 记录完成挑战验证。DNSAuthHandler 通过DNSResolver.LookupTXT查询 DNS TXT 记录,注册了exchange-dns-token令牌交换端点;
  • GitHub 命名空间(如io.github.<user>):通过 GitHub App 访问令牌或 OIDC 流程证明仓库/组织归属,对应 github_at.go 与 github_oidc.go;
  • 此外还有基于 HTTP 挑战(http.go)、OIDC(oidc.go)与无鉴权测试模式(none.go)等实现,便于自建 Registry 时按环境选择鉴权后端。

具体的 GitHub 与域名命名空间的逐步认证操作,见 发布指南。

包归属验证:每种包类型都有明确的"所有权凭证"

所有包都必须携带能证明发布者拥有它的元数据。这一机制防止有人把别人的包绑定到自己控制的 server 记录上。上游项目对此的安全动机在 registry 项目 issue #96 中有专门讨论。

各 Registry 类型的具体验证要求详见 包类型文档(每种 registry 都有 "Ownership Verification" 一节)。从本仓库源码可以印证各类型的验证手段:

Registry 类型所有权凭证源码位置
NPM包的package.json元数据中必须有mcpName字段,且取值与 server name 完全一致ValidateNPM
PyPI包的 description(README)中必须包含mcp-name: <server-name>令牌pypi.go
NuGet包的 README 中必须包含mcp-name: <server-name>令牌nuget.go
Cargocrates.io 上该版本的渲染 README 中必须包含mcp-name: <server-name>令牌cargo.go
OCI/Docker镜像标签(label)io.modelcontextprotocol.server.name必须等于 server nameValidateOCI
MCPB仅允许 GitHub / GitLab Releases 下载链接mcpb.go

几个源码层面的实用细节:

  • NPM 的mcpName必须精确匹配。validateNPMPackage 会请求{baseURL}/{identifier}/{version}元数据端点;缺失mcpName时,错误信息会直接告诉你该往package.json加什么:"NPM package '%s' is missing required 'mcpName' field. Add this to your package.json: \"mcpName\": \"%s\""。取值不匹配时则报ownership validation failed. Expected mcpName ... got ...
  • NPM 对 404 做了精细区分。当版本元数据返回 404 时,npmVersion404Error 会用 HEAD 请求探测包级端点,区分"包不存在"、"包存在但版本尚未同步"(新发布可能有传播延迟)与"上游瞬时故障(429/5xx)"三种情况,给出可操作的重试建议,而不是笼统地报"未找到"。
  • README 令牌采用边界锚定匹配。PyPI/NuGet/Cargo 的mcp-name:令牌必须后接空格、换行或 HTML 标签等边界;如果令牌后面紧贴了其他字符(比如mcp-name: foo与你要的mcp-name: food混淆),错误信息会明确指出"请放到单独一行并重新发布"(见 nuget.go、cargo.go)。
  • OCI 验证失败是"失败关闭"(fail closed)。由于io.modelcontextprotocol.server.name标签是官方 Registry 对 OCI 包唯一的归属凭证,ValidateOCI 在遇到 429 限流时不会放行,而是返回可重试错误;私有镜像(401/403)会明确提示"仅支持公共镜像"。
  • OCI 包的字段约束identifier必须是规范引用(如docker.io/owner/image:1.0.0),不允许再带registryBaseUrlversionfileSha256字段,版本信息包含在identifier中(tag 或@sha256:digest 均可)。
  • 包级验证在EnableRegistryValidation配置开启时执行,入口是 ValidatePublishRequest:它先做_meta扩展校验,再对packages数组逐包调用ValidatePackage,任一包失败即整体失败,错误信息会带上包序号与 identifier。

受限的 Registry Base URL:只允许受信任的公共源

官方 Registry 只接受受信任的公共 Registry,私有 Registry 与替代镜像一律拒绝。支持的清单如下:

Registry 类型允许值
NPMhttps://registry.npmjs.org
PyPIhttps://pypi.org
NuGethttps://api.nuget.org/v3/index.json
Cargohttps://crates.io
Docker/OCIDocker Hub(docker.io)、GitHub Container Registry(ghcr.io)、Quay.io(quay.io)、Google Artifact Registry(*.pkg.dev)、Azure Container Registry(*.azurecr.io)、Microsoft Container Registry(mcr.microsoft.com
MCPBhttps://github.comhttps://gitlab.com的 Releases 下载链接

源码层面的印证:

  • 固定的 Base URL 常量集中定义在 pkg/model/constants.go(RegistryURLNPMRegistryURLPyPIRegistryURLNuGetRegistryURLCratesRegistryURLGitHubRegistryURLGitLab等)。以 NPM 为例,ValidateNPM 要求registryBaseUrlhttps://registry.npmjs.org完全相等,否则返回"registry type and base URL do not match"错误(该错误定义于 constants.go)。
  • OCI 的白名单是唯一的"域名集合"型规则,实现在 allowedOCIRegistries 与 isAllowedRegistry:精确匹配docker.ioregistry-1.docker.ioindex.docker.io(Docker Hub 的 API 端点别名)、ghcr.ioquay.iomcr.microsoft.com,外加两个通配后缀*.pkg.dev(Google Artifact Registry)与*.azurecr.io(Azure Container Registry)。单元测试 oci_test.go 覆盖了通配主机(如myregistry.azurecr.ious-west1-docker.pkg.dev/...)与固定主机的放行行为。不在白名单内的 registry 会返回unsupported OCI registry错误。

_meta命名空间限制:只保留 publisher-provided 数据

server.json中的_meta字段允许发布者携带自定义元数据,但发布到官方 Registry 时有严格限制:只有io.modelcontextprotocol.registry/publisher-provided键之下的数据会被保留_meta对象中的任何其他键都会在发布时被静默丢弃——既不存储也不会在 API 中返回。

对应地,ServerMeta 类型 中_meta只有一个PublisherProvided字段(JSON 标签即为io.modelcontextprotocol.registry/publisher-provided),这从数据结构层面保证了其他键根本无法进入存储。

示例:

{ "_meta": { "io.modelcontextprotocol.registry/publisher-provided": { "tool": "ci-publisher", "version": "1.0.0", "custom_data": "your data here" }, "some.other.key": { // 该键会被丢弃,不会被保留 } } }

大小限制:publisher-provided 扩展的序列化 JSON 上限为4KB(4096 字节),超限会导致发布失败,错误信息中会给出实际字节数。该限制由 validatePublisherExtensions 实现,错误消息格式为:

_meta.io.modelcontextprotocol.registry/publisher-provided extension exceeds 4KB limit (%d bytes)

推荐做法:按反向域名做子命名空间

publisher-provided元数据变大、或来自多个来源(例如 GitHub 专属提示加上自家 CI 工具的元数据)时,按反向 DNS 子键分组是避免键冲突的实用惯例:

{ "_meta": { "io.modelcontextprotocol.registry/publisher-provided": { "com.github": { "serverDisplayName": "My Server" }, "io.example.ci-publisher": { "tool": "ci-publisher", "version": "1.0.0" } } } }

需要说明的是:该惯例不被强制。简单场景下扁平键完全可以,仓库内的既有示例也使用扁平形式;只有当元数据来自多个来源时才建议改用命名空间子键形式。

注意区分:server.json_meta与 API 响应中的_meta

server.json里的_meta与 Registry API 响应返回的_meta两个不同的东西

  • server.json_meta包含发布者自定义元数据,位于io.modelcontextprotocol.registry/publisher-provided之下;
  • API 响应中_meta是响应级别的独立属性(不在server.json内部),承载 Registry 托管的元数据,包括status(生命周期状态:active、deprecated、deleted)、publishedAt(首次发布时间)、updatedAt(最近更新时间)、isLatest(是否为最新版本)。

你发布的内容(server.json):

{ "name": "io.github.example/my-server", "version": "1.0.0", "description": "My MCP server", // ... 其他字段 ... "_meta": { "io.modelcontextprotocol.registry/publisher-provided": { "tool": "ci-publisher", "version": "2.0.0" } } }

Registry API 返回的内容:

{ "server": { "name": "io.github.example/my-server", "version": "1.0.0", "description": "My MCP server", // ... 其他字段 ... "_meta": { "io.modelcontextprotocol.registry/publisher-provided": { "tool": "ci-publisher", "version": "2.0.0" } } }, "_meta": { // 响应级别的 Registry 托管元数据 "status": "active", "publishedAt": "2024-01-15T10:30:00Z", "updatedAt": "2024-01-15T10:30:00Z", "isLatest": true } }

可以看到 API 响应中存在两个_meta:一个在server对象内部(从 server.json 原样保留的发布者数据),另一个在响应级别(Registry 自动添加的托管元数据)。Registry 托管元数据无法被发布者设置或覆盖。从源码可以确认这一点:ServerResponse 的结构正是server(内含 ServerMeta)加上响应级Meta,而后者实际包装的是 RegistryExtensions(status/statusChangedAt/statusMessage/publishedAt/updatedAt/isLatest),JSON 键为io.modelcontextprotocol.registry/official。完整的响应结构参见 官方 Registry API 文档 与 OpenAPI 定义。

如何在发布前自查

结合上述规则,发布前可以用仓库自带工具链自查:

  1. 用 server.schema.json(当前版本日期为2025-12-11,见 constants.go)对server.json做结构校验;仓库提供了 validate-schemas.sh 等脚本用于校验 schema 本身。
  2. 检查各包的所有权凭证是否就位:NPM 包在package.json中加mcpName;PyPI/NuGet/Cargo 包在 README 中加独立一行的mcp-name: <server-name>令牌;OCI 镜像在 Dockerfile 中加LABEL io.modelcontextprotocol.server.name="<server-name>"(验证器在缺失时会在错误信息中直接给出对应的 LABEL 写法)。
  3. 确认registryBaseUrl在上表白名单内、OCI 包未误用registryBaseUrl/version字段。
  4. 控制_metapublisher-provided的序列化体积在 4096 字节以内。

发布流程的命令行操作(validate/publish等子命令)见 发布指南 与 CLI 参考;集成测试 tests/integration/main.go 中对publisher-provided元数据的逐键比对,可作为"发布后数据是否原样保留"的验收参考。

小结

官方 Registry 的附加验证可以概括为:命名空间靠 DNS/GitHub 等所有权证明把关,包靠各 Registry 的原生元数据凭证(mcpName、README 中的mcp-name:令牌、OCI label)绑定归属,包源靠固定白名单收敛到受信任的公共 Registry,_meta靠单一保留键加 4KB 上限控制体积。这些规则在 validators、registries 验证器 与 auth 处理函数 中均有可核对的实现,遇到发布失败时,对照错误信息中给出的具体字段与期望值(如期望的mcpName、期望的 LABEL 写法)修正后重新发布即可。

【免费下载链接】registryA community driven registry service for Model Context Protocol (MCP) servers.项目地址: https://gitcode.com/GitHub_Trending/registry43/registry

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

TLC5925与R7KA8D2KFLCAC双芯协同实现高精度LED光效交互

1. 这不是“炫技”&#xff0c;而是用两颗芯片把交互体验从“能用”拉到“让人驻足”你有没有遇到过这样的项目&#xff1a;功能逻辑跑通了&#xff0c;用户也能操作&#xff0c;但没人愿意多看第二眼&#xff1f;展厅里观众匆匆走过&#xff0c;教育设备前孩子三分钟热度&…

作者头像 李华
网站建设 2026/9/16 11:01:42

加油站AI智管|把安全标准落到每一次现场作业

摘要&#xff1a;为响应《山西省化工和危险化学品安全生产治本攻坚三年行动实施方案》的硬性要求&#xff0c;加油站正加速部署 AI视频监控 系统&#xff0c;以应对 危化品安全 管理的严峻挑战。本文深度解析传统人工巡检的局限&#xff0c;并系统介绍 魅视&#xff08;AVCiT&a…

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

微信小程序活动记录系统开发全解析

1. 项目概述日常活动记录系统是近年来在个人时间管理和企业员工效率分析领域逐渐兴起的一类应用。基于微信小程序的实现方案&#xff0c;因其无需安装、即用即走的特性&#xff0c;正在成为这类工具的主流开发方向。这个项目完整包含了小程序前端、后端服务、数据库设计以及配套…

作者头像 李华