章节导航 第 7 章 / 共 21 章
注册系统:一切的基石
Registry 泛型设计、装饰器 vs 懒加载、元数据驱动的零导入发现、Processor 管道、自动依赖安装
为什么注册系统是第一章
Nexus 有 1047 个文件,但理解框架只需要从一个类开始:Registry。
所有核心抽象——Agent、Task、Tool、Executor、OpenAI Client、Runtime Provider、Span Processor——都通过 Registry 注册、发现、获取。理解了 Registry,就理解了 Nexus 的骨架。
Registry 的泛型设计
nexus/core/registry.py 只有 394 行,但撑起了整个框架的可扩展性。
# 核心:一个泛型类,5 个具体实例
class Registry(Generic[T]):
def __init__(self, type_name: str, processor=None):
self.type_name = type_name # 'agent', 'task', 'tool', ...
self.processor = processor # 注册时的验证/变换函数
self._registry: dict[str, RegistryEntry] = {}
# 5 个注册表
agent_registry = Registry[AgentFunc]('agent', validate_agent)
task_registry = Registry[TaskFunc]('task', validate_task)
tool_registry = Registry[ToolFunc]('tool', _validate_tool_func)
executor_registry = Registry[Callable]('executor', validate_executor)
openai_client_registry = Registry[type[OpenAICompatibleClient]]('openai_client', ...)
还有 2 个在其他模块中定义的注册表:
runtime_provider_registry(nexus/runtime/providers/registry.py)span_processor_registry(nexus/trace/processors/base.py)
共 7 个注册表,但只有一套代码。泛型设计意味着类型安全——你不会不小心把一个 Agent 注册到 Tool 注册表里。
两种注册方式
方式一:装饰器注册(@register)
直接在函数/类定义处注册。适合手写的扩展代码:
@agent_registry.register('my_agent')
async def run_my_agent(input: MyInput) -> MyOutput:
...
这会立即导入并执行装饰器——对象被加载到内存。
方式二:懒加载注册(add)
只记录名字和 import path,不导入任何代码:
agent_registry.add('swe_agent', 'nexus.extensions.agents.swe_agent.agent::run_swe_agent')
直到有人调用 agent_registry.get('swe_agent') 时,才会触发 importlib.import_module()。
这是 Nexus 框架启动速度的关键——import nexus 时注册了约 100 个对象,但没有导入任何扩展代码。
RegistryEntry 数据结构
@dataclass
class RegistryEntry:
name: str
obj: Any = None # None 表示还没加载
import_path: str | None # 懒加载用的 import path
meta: dict # 元数据
install_commands: list # 依赖安装提示
@property
def is_loaded(self) -> bool:
return self.obj is not None
get() 的逻辑很清晰:
def get(self, name: str) -> T:
entry = self._registry[name]
if entry.is_loaded:
return entry.obj
# 懒加载
Registry.import_module(entry.import_path, entry.install_commands)
return entry.obj
元数据驱动的零导入发现
这是整个框架最精妙的设计。
问题
有 100+ 个扩展模块,每个都有自己的依赖。如果 import nexus 时把它们全导入,会遇到两个问题:
- 启动慢——很多模块有重依赖(playwright、jupyter_client 等)
- 启动失败——缺少某个模块的依赖会导致整个框架 import 报错
解法
完全不导入扩展代码,只读它们的 pyproject.toml。
# nexus/__init__.py
from nexus.core.module_registry import module_registry
module_registry.discover_and_register()
discover_and_register() 的流程:
- 遍历 8 个扫描根目录(
extensions/agents、extensions/tasks等) - 对每个子目录,读取
pyproject.toml(或.py文件的 PEP 723 块) - 解析
[tool.nexus]section,获取声明的对象名和 import path - 对每个声明的对象,调用对应 registry 的
add(name, import_path)
整个过程只读 TOML 文件,不执行任何 Python import。
扫描: extensions/agents/swe_agent/pyproject.toml
解析: [tool.nexus] agents = { swe_agent = "nexus...agent::run_swe_agent" }
注册: agent_registry.add('swe_agent', 'nexus...agent::run_swe_agent')
→ 此时 swe_agent 的代码完全没有被导入
ModuleMeta 数据结构
@dataclass(frozen=True)
class ModuleMeta:
name: str # "swe_agent"
module_path: str # "nexus.extensions.agents.swe_agent"
fs_path: Path # 绝对文件系统路径
base_deps: tuple # 共享依赖
host_extras: tuple # Host 侧额外依赖
runtime_extras: tuple # Runtime 侧额外依赖
objects: dict # {'agents': {'swe_agent': 'import_path'}}
kind: str # 'directory' 或 'single_file'
key → registry 的映射
TOML 中的 key 名不是 registry 的 type_name,需要一层映射:
NEXUS_KEY_TO_REGISTRY_TYPE = {
'agents': 'agent',
'tasks': 'task',
'tools': 'tool',
'openai_clients': 'openai_client',
'executors': 'executor',
'runtime_providers': 'runtime_provider',
'span_processors': 'span_processor',
}
Processor 管道
每个 Registry 可以配置一个 processor 函数,在注册时验证并变换对象。
以 Agent 为例:
def validate_agent(obj, name, meta) -> ProcessorResult:
# 1. 必须是 async callable
if not inspect.iscoroutinefunction(obj):
raise TypeError(...)
# 2. 恰好一个参数,类型是 AgentRunInput 子类
# 3. 返回类型是 AgentRunOutput 子类
# 4. 用 @observe 装饰器包装(集成 Trace)
wrapped_obj = observe(name=f'agent.{name}')(obj)
return ProcessorResult(wrapped_obj=wrapped_obj, meta=meta)
这意味着:每个注册的 Agent 函数都被自动包装了 Trace 埋点。 你写 Agent 时不需要手动加 @observe。Tool 和 Task 同理。
自动依赖安装
当 get() 触发懒加载但 import 失败时:
- 如果
RegistryEntry.install_commands非空,尝试uv pip install或pip install - 如果
NEXUS_AUTO_INSTALL=1,尝试从 ModuleMeta 中获取缺失的依赖并安装 - 都失败了,生成人类可读的安装提示
Failed to import 'nexus.extensions.agents.swe_agent.agent': No module named 'unidiff'
Module 'swe_agent' requires missing packages: unidiff
To install: nexus modules install swe_agent
Or enable: NEXUS_AUTO_INSTALL=1
ContextVar 追踪嵌套导入
一个微妙的设计:_import_registrations ContextVar 追踪 import_module() 过程中发生的所有注册。
为什么需要这个?因为 import_module('nexus.extensions.agents.swe_agent.agent') 可能触发 swe_agent/__init__.py 中的其他 @register() 调用(比如同时注册了一些 Tool)。ContextVar 确保这些嵌套注册都被正确追踪和记录。
设计决策小结
| 决策 | 为什么 |
|---|---|
| 泛型 Registry 而非多个类 | 一份代码,类型安全,统一的 get/add/register API |
| 懒加载 add() | 框架启动不导入扩展代码,启动快、容错好 |
| TOML 元数据驱动 | 发现模块不需要执行 Python,彻底解耦 |
| Processor 管道 | 注册时验证 + 自动包装 Trace,减少手动样板代码 |
| 全局 GLOBAL_STATE | 单例语义,防止重复创建同名注册表 |
注册系统的安全边界
Registry 的懒加载和自动安装机制带来了便利,但也引入了安全考量:
- MCP 安全缺陷启示:2026 年 4 月披露的 MCP STDIO 接口安全漏洞(CVE-2026-30615)表明,外部工具的动态加载可能存在远程代码执行风险。Nexus 的 MCP 工具动态加载(Ch08)和自动依赖安装机制都涉及外部工具执行,需要严格的安全边界。
另一类攻击面:工具被授予的范围(scope),而不是它在哪执行。 上面第 3 条(MCP Tool 默认标记为 RUNTIME、在沙箱内执行)防的是执行位置。SalesBleed(Zenity Labs,2026-09-24 披露,未分配 CVE)说明的是沙箱化管不到的那一半。
攻击链:攻击者往公开的 Web-to-Lead 表单里提交一条含有隐藏指令的线索 → 之后员工正常地问一句”帮我看看最新的线索” → Agent 读到这条记录并按其中的指令,用它自己的 Query Records 子代理去查 Accounts 表 → 把公司名与交易额编进攻击者域名的子域,以 HTML
<img src>标签输出 → 前端自动取图,DNS 查询本身就完成了外泄,全程零点击、不需要受害者点任何链接,也不需要攻击者登录 Salesforce。第二条外泄路径借的是 Slack 的链接展开:Slack 为生成预览自行抓取链接,抓取发生在 Slack 的基础设施上,受害方自己的 DNS 过滤与代理日志看不到。第三条是冒用 Agent 身份在内部 Slack 线程里发钓鱼消息——默认的 Slack Knowledge 子代理模板里的 “Reply to a Slack Thread” 动作既不需要用户确认,也不记录是哪个用户触发的(这一条出自 Zenity 的第二篇报告,见文末出处说明)。
两条关键论断值得原样记住。其一,Zenity 报告原话:「Our payload asked for company names and deal sizes, but the injection could have asked for anything the subagent’s Query Records tool can reach」——没有任何人提升权限,Agent 用的正是它本来就被授予的访问权限。其二,防护失败在解析层:URL 脱敏层(redactor)只认一组固定的顶级域名(
.fun不在其中,而它恰好是app.interactsh.com这类 OOB 测试平台用的),并且脱敏层与渲染层对”URL 在哪结束”的判断不一致——花括号与方括号可以不被脱敏却仍是 URL 的一部分,形如https://random_string.oast.fun/{email}的字符串就能整条穿过去。落到本章的三条推论:① 沙箱化(RUNTIME 标记)不缓解这一类——Agentforce 的子代理是在正常授权内工作的;② “每调用级别的信任评估”应先问”这次调用需要的最小范围是什么”,而不是”这次调用在哪执行”;③ 与下面信任层的
score ≠ 信任背书原则并列,构成信任层的两条实证脚:一条管”排序不能当授权依据”,一条管”授权范围本身就是攻击面”。时间线:SalesBleed 是 Zenity 的两篇报告,不是一篇,引用时要分开——第一篇《0-Click Data Exfiltration on Agentforce》(2026-09-24 披露)给出 06-01 报给 Salesforce、06-02 确认、08-18 修复完成、08-19 验证 Trusted URLs 绕过;第二篇《Hijacking Agentforce in Slack for Anonymous Phishing》(同为 09-24 披露)给出 08-20 确认 Reply to a Slack Thread 已带归属、08-25 Salesforce 称确认步骤仍在改、09-10 称确认步骤预计 09-21 完成、09-21 全部修复确认并测试完毕。Zenity 称 Salesforce 已修复、完整的攻击链不再成立。
无状态化安全影响:2026-07-28 正式版移除 protocol-level session 后,传统的 session-fixation 和 session-hijacking 攻击面自然消除。但新的攻击面可能出现——
_meta对象携带客户端身份信息,需要验证其完整性(防篡改);Mcp-Method/Mcp-Name头若被篡改,可能导致请求被错误路由。
Trace 上下文已进规范:2026-07-28 正式版把
traceparent、tracestate、baggage定为官方_meta键,用途标注为 OpenTelemetry trace context propagation(这是”官方扩展须用io.modelcontextprotocol/前缀、第三方用各自 vendor 前缀”这一规则的特例)。同批官方键还有io.modelcontextprotocol/logLevel与io.modelcontextprotocol/subscriptionId。对 Nexus 的意义在第 5 章:GFCR 的 rollout trace 与跨进程 MCP 调用链可以共用同一个 trace id——若 Nexus 的 MCP Client 在
_meta中透传traceparent,一次 benchmark 评测的完整链路(Nexus → MCP Server → 工具)就能串进同一条 trace,批量评测的故障归因不再需要在两套孤立链路之间人工对齐。⚠️ 安全侧:
_meta由客户端提供,上一段的完整性要求同样适用于 trace 字段——不要基于客户端提供的traceparent做授权决策。⚠️
_meta成员本身可能是缺失的,不要假定它存在。 MCP Python SDK 2.3.0(2026-10-02)起,对 2025-11-25 及更早的连接不再发送空的"_meta": {}(2.x 原先每个请求都发,部分服务端会拒绝它),ping与不带游标的 list 请求则连params成员都不发;接收侧ctx.meta现在是None而非{},中间件对无 params 的请求看到ctx.params为None。2026-07-28 连接不受影响(#3628)。对 Nexus 的含义直接落在上面这条建议上:若 MCP Client 要在
_meta里读traceparent,必须处理_meta缺失这一路,不能写成ctx.meta["traceparent"]。这不是边缘情况——12 个月的迁移窗口内新旧连接都会遇到,旧连接上_meta干脆不出现。同批变更里还有一条相关:initialize在未配置时不再发experimental(原为"experimental": {},#3614),所以读capabilities.experimental的代码同样要处理None。
-
自动安装的风险:
NEXUS_AUTO_INSTALL=1允许自动pip install缺失依赖——这意味着一个恶意的pyproject.toml可以声明任意包为依赖。建议在生产环境关闭此选项,仅使用nexus modules install显式安装。 -
MCP 工具审计需求:MCP 工具不经 Pydantic 验证(Ch09),输入可信度低于静态注册 Tool。建议 MCP Tool 默认标记为 RUNTIME 类型(在沙箱内执行),避免在 Host 侧直接执行不可信代码。
意图感知工具检索:注册系统的进化方向
当前 Registry 的 get(name) 是精确查找——你需要知道工具叫什么。但当工具数量从 56 个扩展到数千个时,简单的 get() 不够用。
Zylos Research(2026-03)对 MCP、A2A、ANP、WebMCP、AGNTCY、Spring AI 等实现的综合调研提出了三层架构共识,这为注册系统的进化提供了清晰的框架:
第一层:广告层(Registry/DHT)——工具在哪里、怎么找到它。
MCP Registry(2025-09 上线,10,000+ 个服务器条目,SDK 月下载量 9,700 万+,Claude 连接器 950+、月下载 4 亿+,六大主流宿主平台(Claude Desktop/Code、Cursor、Codex CLI、Windsurf、VS Code/Copilot)一等公民支持)已提供生产级的工具发现基础设施:REST API 支持运行时动态工具发现、Verified Server 信任评分、联邦发现(企业私有子注册表 + 全局目录兼容)。对 Nexus 而言,module_registry.discover_and_register() 可扩展为双重发现源:本地 TOML 扫描 + 远程 MCP Registry API 查询。
AWS Agent Registry(2026-04 预览版,AgentCore 组件)则提供了云平台级方案:语义搜索 + 关键词搜索、IAM/OAuth 访问控制、审批工作流、CloudTrail 审计跟踪、基于 URL 的自动元数据发现(从运行中的 MCP Server 自动拉取工具 schema)。
第二层:语义匹配层(Semantic Matching)——选哪些工具。
S1-NexusAgent(arXiv:2602.01550)的 Faiss 向量索引方案可作为此层的参考实现。但不同工具规模需要不同的匹配策略:
| 工具规模 | 推荐策略 | 原因 |
|---|---|---|
| ~30 | 关键词搜索 | 向量检索开销不值得 |
| ~500 | 向量/语义搜索 | 关键词区分度不足 |
| ~5,000 | 层级发现(MCP-Zero) | 平面索引性能退化 |
| ~10,000+ | LLM 生成请求 | 预定义索引无法覆盖长尾 |
Nexus 当前 56 个工具处于关键词→向量搜索的过渡区间。
第四层:联邦发现层(Federation)——跨注册中心搜索。
ARD(Agentic Resource Discovery,2026-06-17,Google/Microsoft/Hugging Face 等 12 方联合草案)在传统三层架构之上增加了联邦发现层。其核心设计是 /.well-known/ai-catalog.json 作为每个域名的能力自述文件,Registry 爬取并跨域聚合。对 Nexus 的启示:module_registry.discover_and_register() 的远程发现逻辑可以从”查询单一 Registry API”扩展到”查询 ARD 兼容的联邦 Registry”——不改变本地 TOML 骨架,但丰富远程发现源。
ARD 的注册中心侧已出现实际实现:阿里巴巴 Nacos 3.3 落地 ARD 联邦发现规范,成为 ARD 在注册中心侧的采纳新案例。不过需如实标注现状——ARD 仍处 v0.9 draft,OpenAI/Anthropic 尚未加入支持方。
🔄 锚点刷新(2026-10-03):上面”成为 ARD 在注册中心侧的采纳新案例”这句容易读成”已经可用”,需要加一条现状限定。GitHub Releases 实测:3.3.0-RC 发布于 2026-09-21,
prerelease = true;上一个 GA 是 3.2.4(2026-08-27)。也就是说 3.3 从 BETA(2026-08-06)走到 RC(09-21),至今(2026-10-03)仍未 GA。本章凡涉及 3.3 的表述都应带这条限定。资源类型也扩了。官方 AI Registry 文档已把资源类型从本章记载的 Skill / Agent / MCP Server / Prompt 扩到六类,新增 AgentSpec(Agent 规范包),并明确 Agent Registry(可调用入口)与 AgentSpecs Registry(规范包)是两种不同的资源——可配合使用,但不是一回事。这对应到 Nexus 的映射上,是”能调这个 Agent”与”拿到这个 Agent 的规范定义”两条独立查询,不要合成一条。
RAD(Remote Agent Discovery)侧还有一组兼容性窗口,对判断”联邦发现”的落地节奏有用:官方
agent-api-spec以 RAD 六个根消息为唯一领域模型、SERVER_RAD_V1做能力协商;遗留 Console A2A API 支持到 Nacos 3.4 线,遗留 Admin/Maintainer A2A API 保留到 Nacos 4.0 兼容边界。窗口期内遗留 A2A Endpoint API 不重写到新的版本中立 Agent Naming 服务——后果是旧客户端无法构造跨 Version 的发布批次。⚠️ Nacos 3.3 的 GA 时间本轮无公开信息。若读者读到本节时 3.3 已 GA,请按新状态重新理解上文限定。
Nacos 3.3 的落地细节(3.3.0-RC,2026-09-21 发布,pre-release;⚠️ 截至 2026-10-03,3.3 仍未 GA,当前最新 GA 为 3.2.4,2026-08-27):该版本把 ARD 实现为一个接入注册中心的统一资源搜索引擎——关键词 + 向量混合检索,共 6 个端点,返回统一规约为「资源类型 · 相关性(0–100)· 访问入口」,覆盖 Skill / Prompt / MCP 等资源类型的跨型发现;检索之外还有探索、制品获取、可见性过滤与持久化索引。同期落地的还有协议中立的 Agent 注册(注册、持久化、端点发现、Java SDK、Console API,以及 legacy A2A 兼容路由)、分布式锁(可重入/非可重入、watchdog 续期、FIFO 等待、Raft 一致性)、SkillSpector 作为 AI 发布流水线、以及插件级可见性授予/回收 API。
三条设计原则值得 Nexus 直接借鉴:
score ≠ 信任背书——检索相关性不等于可信度。这与上面「注册系统安全边界」一节的主题同构:召回层给出的排序不能当作授权依据。- 不替代 MCP / A2A,且不负责执行——ARD 只做发现,明确不侵入执行面。
- 事实源与派生数据分离——事实资源先落库,派生索引异步构建且可重放、幂等重建,失败与遗漏都能补齐。
索引架构之外还有一项同期增强:RAD(Remote Agent Discovery,按任务意图与期望调用方式返回可远程调用的 Agent)与单资源授权(资源键 = Namespace + 类型 + 名称)。版本路线为 3.3 初步落地 → 3.4 发现增强 → 4.0 Nacos 自身智能化。
⚠️ 待核实:此前记录的「AWS 于 2026-08-24 公开支持 ARD 作为 AWS Agent Registry(Bedrock AgentCore)联邦层」本轮未能复现,不写入正文。
第三层:信任层(Per-invocation Trust)——执行时怎么验证。
MCP Registry 的 Verified Server 信任评分和 AWS Agent Registry 的审批工作流为此层提供了工业参考。对 Nexus 而言,RUNTIME 类型标记(Ch10 沙箱内执行)已是信任层的雏形,但需要细化为每调用级别的信任评估。
注册系统可能需要从 get(name) 扩展为 search(intent, top_k, trust_level) 的语义检索接口。
这个方向现在是官方 roadmap 的一项,可以由”本书推断”升级为”与官方同向”。 MCP 官方于 2026-08-22 发布《The New MCP Roadmap》(作者为两位 Lead Maintainer),把工作组织成 五个优先领域(注意是五项,不是此前流传的四项):
- Agentic messaging primitives —— 服务端发起事件(webhooks / channels,让客户端不必轮询)、跨 Agents / Transports / Triggers & Events 三个工作组的组合评审,以及把 Tasks 扩展(SEP-2663) 养熟以便移进规范本体。
- HTTP-native transport unification and hardening —— 2026-07-28 之后远程 MCP server 与任何其他 HTTP 工作负载无异,下一步是把这个模式覆盖到其他部署形态(包括本地 server 走 stdio 上的 Streamable HTTP),收敛到单一传输。
- Agent identity and enterprise-ready security —— 现有授权围绕”人在浏览器里点同意”设计,而越来越多的调用方是以云工作负载身份运行、代表不在场的用户、或向下级子代理下放更窄权限的 Agent。要标准化地识别与信任这些 Agent 身份,路线是 DPoP(RFC 9449)、Workload Identity Federation、ID-JAG grant 与标准 token exchange。
- Improved primitives —— 两块:一是
tools/call的结果契约标准化(同一份输出可以有多种形态,server 开发者今天无法知道客户端会把哪种喂给模型);二是规模问题。 - Improved SDK developer experience。
第 4 项的后半块几乎就是本节这句话的官方版。原文是:连上一个有一百个工具的 server,意味着在用户问出第一个问题之前,模型就要为整个工具面付钱,而且工具选择质量随列表变长而下降;因此官方正在启动 progressive discovery——server 只暴露一个小入口,随着对话收窄再逐步揭示更多目录。
与本章的对位关系很整齐:第 4 项对应 search(intent, top_k, trust_level) 的语义检索;第 1 项的 Tasks 对应本章 §「Tasks 扩展与 Installed Agent 的协同」;第 3 项的 Agent 身份与下放权限,恰好是上面 SalesBleed 那一类”工具范围即攻击面”问题的正面应对方向。换句话说,本章从注册/发现角度独立推出的三个结论,官方 roadmap 里有三项在往同一处走。
⚠️ 请把 roadmap 当方向声明读,不当”已实现”读。原文自己的说法是:落在这些优先领域内的 SEP 走加速评审、最可能被接受;领域外的提案不会被自动拒绝,但维护者的评审时间优先给这些领域。
在设计决策表中,可以补充与 lazyregistry 的对比:
| 对比维度 | Nexus Registry | lazyregistry |
|---|---|---|
| 发现机制 | TOML 元数据驱动 | import string 直接注册 |
| 验证管道 | Processor 管道(验证 + 自动包装) | 无 |
| 命名空间 | 无 | 支持分层命名空间 |
| 特殊模式 | 无 | pretrained model save/from_pretrained |
Nexus 的 TOML 驱动更适合框架级跨包发现,lazyregistry 更适合轻量级库内使用。
AI Agent 注册系统生态对比
Nexus Registry 的定位是框架级模块发现,但 AI Agent 领域已经涌现了多种注册表方案:
| 维度 | Nexus Registry | MCP Registry | AWS Agent Registry | AgenticMesh |
|---|---|---|---|---|
| 定位 | 评测框架模块发现 | MCP Server 全局目录 | 云平台级 Agent/Tool 治理 | 去中心化 Agent 发现 |
| 发现机制 | TOML 元数据驱动 | REST API + 语义搜索 | 语义/关键词搜索 + 自动元数据发现 | DHT 分布式哈希 |
| 信任模型 | 无(框架信任所有注册项) | Verified Server 信任评分 | IAM/OAuth + 审批工作流 + CloudTrail | 信誉系统 |
| 适用场景 | 跨包 Python 模块 | 运行时动态工具发现 | 企业治理/合规 | 去中心化生态 |
| 联邦能力 | 无 | 企业私有子注册表 + 全局目录 | AWS 区域隔离 | 天然联邦 |
Nexus 的 TOML 驱动适合框架级跨包发现(零网络依赖、确定性高),MCP Registry 适合运行时动态发现(生态广、实时更新),AWS Agent Registry 适合企业治理(合规审计、访问控制),AgenticMesh 适合去中心化场景(无单点依赖)。四者互补而非竞争——Nexus Registry 可作为 MCP Registry 的本地缓存层,AWS Agent Registry 可作为 MCP Registry 的企业治理增强层。
| 维度 | ARD (Agentic Resource Discovery) |
|---|---|
| 定位 | 跨协议 Agent 能力发现层 |
| 发现机制 | /.well-known/ai-catalog.json + Registry 爬取 + 语义搜索 |
| 信任模型 | 域名所有权即密码学身份 + 可选 trustManifest 合规证明 |
| 适用场景 | 联邦注册中心跨域搜索(不替代 MCP/A2A,是上层发现) |
| 联邦能力 | 原生联邦——每个域名自建 catalog,Registry 跨域聚合 |
| 注意 | ARD 当前为 2026-06-17 v0.9 draft(Google/Microsoft/Hugging Face 等 12 方联合),Anthropic/OpenAI 客户端支持待定。GitHub Copilot Agent Finder 为首个生产级实现,Nacos 3.3 为注册中心侧采纳案例。 |
Harbor 的数据集注册表:注册的是”内容”,不是”代码”
上面这张表比的都是”怎么发现一个模块”。Harbor 提供的是一个不同粒度的样本:它注册的不是代码对象,而是数据集内容。
registry.json 是个扁平数组,条目长这样(逐字节节选):
{
"name": "aider-polyglot",
"version": "1.0",
"description": "A polyglot coding benchmark ...",
"tasks": [
{
"name": "polyglot_java_zipper",
"git_url": "https://github.com/laude-institute/harbor-datasets.git",
"git_commit_id": "f30b14415dd733c83627204bad0af69a89ceb46f",
"path": "datasets/aider_polyglot/polyglot_java_zipper"
}
]
}
决定它性质的是三个字段:git_url + git_commit_id + path——每个 task 都锁到了具体 commit。跑 harbor run -d terminal-bench@2.0 取回的是那个 commit 的任务目录,而不是”仓库当前长什么样”。
| 维度 | Nexus Registry | Harbor registry.json |
|---|---|---|
| 注册对象 | Python 对象(agent / task / tool / …) | 数据集与 task 目录(Git 上的内容) |
| 版本 | 无版本字段(RegistryEntry 只有 name / import_path / 元数据) | 双层:version + 每个 task 的 git_commit_id |
| 复现单位 | ”装了这个包的这个版本" | "取了这个 commit 的这几个目录” |
| 信任模型 | 无(框架信任所有注册项) | 同样无——但内容一致性由 Git 保证;注意这不等于作者身份可信 |
| 典型规模 | import nexus 时约 100 个对象 | 80 个数据集、数万 task |
关键差别一句话:Nexus 注册”能执行什么”,Harbor 注册”跑的是哪一份数据”——前者解决可发现性,后者解决可复现性。而可复现性恰恰是上表里 Nexus 没有抓手的一项:RegistryEntry 没有任何内容标识,同一份 task.py 改一行,nexus modules 看不出区别。
这直接接上第 13 章那处缺口(runs 表无 schema 版本、无幂等键、无从记录”这次跑在哪个沙箱上”):复现链上缺的那一环,Nexus 在注册层和数据层都没有提供。 低成本的补法也不是照搬 registry.json,而是给 TaskRunInput 带上任务集的内容标识——哪怕先只是一个 dataset_revision 字符串。先能回答”这次跑的是哪份题”,再谈可复现。
⚠️ Harbor 侧数字(80 个数据集 / 数万 task)核于 2026-10-10,对应仓库 v0.24.0。该文件随版本频繁增删数据集,引用前请复核。
MCP Registry 对接的技术可行性(已适配 2026-07-28 正式版)
MCP 2026-07-28 引入了自协议诞生以来最重大的变更——彻底无状态化,直接改变了 Registry 对接的技术前提。
1. server/discover 替代 initialize
旧方案(2025-11-25 协议)依赖 initialize/initialized 握手获取服务器能力和会话 ID。2026-07-28(SEP-2575/2567)移除握手和 Mcp-Session-Id,每个请求自包含——版本和能力信息通过 _meta 对象携带。对 Nexus 而言:
module_registry.discover_and_register()的远程发现流程变为:调用 MCP Registry API → 获取 server.json → 对每个 server 调用server/discover获取运行时能力(tools/resources/prompts 全量列表)server/discover的响应遵循 SEP-2549 标准化缓存控制(ttlMs/cacheScope),可缓存以减少远程调用频率
版本协商头是必填行为,不是可选项:除 _meta 外,HTTP 传输上每个请求还需携带 MCP-Protocol-Version 头声明自己使用的协议版本。若服务端未实现该版本(不认识,或认识但选择不支持),必须回 UnsupportedProtocolVersionError 并列出其支持的版本。Nexus 的 MCP Client 实现若省略该头,在与严格实现的 Server 对接时会直接失败而非降级。
⚠️ “无状态”不等于”不能多轮”:2026-07-28 规范把 MRTR(Multi Round-Trip Requests,多轮往返请求)列为官方消息模式之一,与 request/response、subscribe/notify 并列(规范路径
/basic/patterns/mrtr)。服务端仍可在处理单个请求的过程中多次回调客户端(例如向客户端补要参数),只是不再依赖长连接的会话状态。对 Nexus 的 MCP Client,这意味着去掉 session 管理不等于去掉多轮交互能力,需要实现的是”每次回调都自带上下文”的多轮处理,而不是把交互压平成一次性请求。
2. Mcp-Method/Mcp-Name 头路由简化网关集成
新协议强制 Streamable HTTP 请求携带 Mcp-Method 和 Mcp-Name 头(SEP-2243)。网关可在不解包 JSON-RPC body 的情况下路由请求。对 Nexus 的益处:MCP 工具调用可直接在网关层分发,与 Nexus 现有的 LOCAL vs RUNTIME 分发逻辑天然兼容——网关层识别 Mcp-Method,RUNTIME 类型工具在沙箱内执行,LOCAL 类型转发到 Host。
3. server.json → RegistryEntry 映射不变,但新增字段
映射策略基本不变(mcp_{server_name}_ 前缀 + source: "mcp-remote" 标记),但新协议新增的 ttlMs 和 cacheScope 字段可作为 RegistryEntry 的 freshness 元数据,驱动缓存失效策略。
4. Tasks 扩展与 Installed Agent 的协同
新 Tasks 扩展取代旧的实验性 Tasks API,标准化了 working/input_required/completed/failed/cancelled 五状态机。与 Nexus 的 Installed Agent 模式互补——长时间运行的 MCP 任务可通过 Tasks 状态机追踪,Nexus Runner 可监听状态变更并同步到训练循环。
✅ 2026-07-28 规范已正式发布(三处独立证据一致:规范页版本选择器显示
Version 2026-07-28 (latest);文档站默认路径为/docs/2026-07-28/;llms.txt将其与 2024-11-05 / 2025-03-26 / 2025-06-18 / 2025-11-25 并列为已发布版本路径,草案另有/docs/draft/)。⚠️ 本节此前”建议在正式发布后再做工程对接”的结论已作废——该建议写于 RC 期(2026-07 中旬),而 2026-07-28 既是预定发布日也早已过去。现在可以开始对接了。
仍需留意的是 SDK 成熟度:原文记载的「SDK Beta 已可用(Python v2、TypeScript v2、Go、C#)」是 RC 期状态,GA 之后的 SDK 版本号与支持矩阵须重新核实后再引用(本轮未核实)。
SEP-2577 标记 Roots、Sampling、Logging 为 Deprecated(12 个月迁移窗口),现有依赖这些特性的 MCP Server 需要在 2027-07-28 前迁移。
⚠️ “可以对接”不等于”连得上”。 上面这句结论本身没错,但缺一条量化边界。第三方对官方 MCP registry 端点的实测(2026-10-01,取官方 v0 REST API 前 900 条、按 endpoint URL 去重后取 hostname 首字母 a–b 的连续切片共 186 个端点,05:27Z 与 06:06Z 双探针)显示,在线 MCP 生态同时存在五个协议修订:
类别 数量 占 186 个端点 Auth-gated(匿名探针被 HTTP 401 拦住) 86 46% 回答旧 wire 的合计 65 35%(2025-11-25 占 36 / 2025-06-18 占 21 / 2025-03-26 占 5 / 2024-11-05 占 3) 回答 2026-07-28 新 wire 7 4% 瞬时错误 28 15% 关键比例要连带分子分母一起读:在返回了协议版本的 72 个端点中,讲新 wire 的只有 7 个,占 9.7%。只印”4%“会变成”只有 4% 支持新协议”的误读——分母其实是 186,另有 46% 根本探不到。这 7 个里 6 个可证明是在被提供 2026-07-28 时才升级协商的(真协商),1 个是写死的;且其中 3 个由同一运营方持有,所以它不是 7 个独立早期采用者,而是一个 operator-cluster。39 分钟后的复探类别形状完全一致。
落到 Nexus 的设计上,这条数据给出一个硬约束:
module_registry.discover_and_register()若要接远程发现,必须把”协议版本”做成一等字段并逐 server 记录,不能假设 registry 里的条目都讲同一版协议;server/discover的返回要当作能力协商的结果存下来,而不是一次性握手。⚠️ 来源性质:该测量由第三方(dev.to)自行实施,非 MCP 官方发布;切片是 a–b 的连续切片而非随机抽样,作者自己也标了 caveat。数值可引,但必须带来源与方法。
一个容易踩的混淆:registry 的条目 schema ≠ server 讲的协议版本。 本轮实测官方 registry REST API(
GET https://registry.modelcontextprotocol.io/v0/servers?limit=1,HTTP 200)返回的第一条是:{"server": {"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", "name": "ac.inference.sh/mcp", "version": "1.0.0", "remotes": [{"type": "streamable-http", "url": "https://sh.inference.ac"}, ...]}, "_meta": {...}}注意
$schema里的 2025-12-11——那是 registry 的 server 条目 schema 定版日期,它早于协议修订日 2026-07-28。也就是说,一个 server 完全可能”在 registry 里有一条完全合规的条目”,却”只讲 2025-11-25 的 wire”。这正是上面那 9.7% 的结构性根源:条目合规与对话能力是两条独立的轴。工程含义很直接:RegistryEntry 的元数据里应当增加一个
protocol_version字段(与ttlMs/cacheScope并列),从server/discover的协商结果里取,而不是从 registry 条目里推断。分页游标走响应的metadata.nextCursor,remote 端点的type为streamable-http。
授权侧硬化:2026-07-28 规范的授权部分以一整套 OAuth 2.x 扩展为底座,其中两项与注册/发现强相关:
- RFC 9207(Authorization Server Issuer Identification):授权响应中显式携带
iss参数,用于防御混血授权服务器攻击;支持该参数的授权服务器必须在元数据中把authorization_response_iss_parameter_supported置为true- CIMD(Client ID Metadata Documents,
draft-ietf-oauth-client-id-metadata-document-00):规范对授权服务器与 MCP Client 的要求是 SHOULD 支持;而 DCR(RFC 7591)已被明确标注为 deprecated,仅为向后兼容保留同批引用的还有 RFC 8707(Resource Indicators)与 RFC 9728(Protected Resource Metadata,服务端 MUST 实现)。对 Nexus 的推论:对接支持 MCP 授权的服务端时,应优先走 CIMD 路径而非 DCR。
与 ARD 的定位关系:ARD 不替代 MCP Registry,而是提供跨 MCP Registry 的联邦搜索层。对 Nexus 而言,两者互补——MCP Registry 作为具体工具的运行时目录(“这个 server 有哪些 tools”),ARD 作为跨 Registry 的能力搜索引擎(“哪个 server 能处理退款”)。Nexus 当前的 TOML 本地发现 → MCP Registry 远程发现 → ARD 联邦发现,构成三层递进的发现能力。