第 7 章 第二部分:架构原理

注册系统:一切的基石

Registry 泛型设计、装饰器 vs 懒加载、元数据驱动的零导入发现、Processor 管道、自动依赖安装

Nexus Registry 模块发现 懒加载 设计模式

为什么注册系统是第一章

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 时把它们全导入,会遇到两个问题:

  1. 启动慢——很多模块有重依赖(playwright、jupyter_client 等)
  2. 启动失败——缺少某个模块的依赖会导致整个框架 import 报错

解法

完全不导入扩展代码,只读它们的 pyproject.toml。

# nexus/__init__.py
from nexus.core.module_registry import module_registry
module_registry.discover_and_register()

discover_and_register() 的流程:

  1. 遍历 8 个扫描根目录(extensions/agents、extensions/tasks 等)
  2. 对每个子目录,读取 pyproject.toml(或 .py 文件的 PEP 723 块)
  3. 解析 [tool.nexus] section,获取声明的对象名和 import path
  4. 对每个声明的对象,调用对应 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 失败时:

  1. 如果 RegistryEntry.install_commands 非空,尝试 uv pip install 或 pip install
  2. 如果 NEXUS_AUTO_INSTALL=1,尝试从 ModuleMeta 中获取缺失的依赖并安装
  3. 都失败了,生成人类可读的安装提示
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 的懒加载和自动安装机制带来了便利,但也引入了安全考量:

  1. 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。

  1. 自动安装的风险:NEXUS_AUTO_INSTALL=1 允许自动 pip install 缺失依赖——这意味着一个恶意的 pyproject.toml 可以声明任意包为依赖。建议在生产环境关闭此选项,仅使用 nexus modules install 显式安装。

  2. 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 直接借鉴:

  1. score ≠ 信任背书——检索相关性不等于可信度。这与上面「注册系统安全边界」一节的主题同构:召回层给出的排序不能当作授权依据。
  2. 不替代 MCP / A2A,且不负责执行——ARD 只做发现,明确不侵入执行面。
  3. 事实源与派生数据分离——事实资源先落库,派生索引异步构建且可重放、幂等重建,失败与遗漏都能补齐。

索引架构之外还有一项同期增强: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),把工作组织成 五个优先领域(注意是五项,不是此前流传的四项):

  1. Agentic messaging primitives —— 服务端发起事件(webhooks / channels,让客户端不必轮询)、跨 Agents / Transports / Triggers & Events 三个工作组的组合评审,以及把 Tasks 扩展(SEP-2663) 养熟以便移进规范本体。
  2. HTTP-native transport unification and hardening —— 2026-07-28 之后远程 MCP server 与任何其他 HTTP 工作负载无异,下一步是把这个模式覆盖到其他部署形态(包括本地 server 走 stdio 上的 Streamable HTTP),收敛到单一传输。
  3. Agent identity and enterprise-ready security —— 现有授权围绕”人在浏览器里点同意”设计,而越来越多的调用方是以云工作负载身份运行、代表不在场的用户、或向下级子代理下放更窄权限的 Agent。要标准化地识别与信任这些 Agent 身份,路线是 DPoP(RFC 9449)、Workload Identity Federation、ID-JAG grant 与标准 token exchange。
  4. Improved primitives —— 两块:一是 tools/call 的结果契约标准化(同一份输出可以有多种形态,server 开发者今天无法知道客户端会把哪种喂给模型);二是规模问题。
  5. 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 Registrylazyregistry
发现机制TOML 元数据驱动import string 直接注册
验证管道Processor 管道(验证 + 自动包装)无
命名空间无支持分层命名空间
特殊模式无pretrained model save/from_pretrained

Nexus 的 TOML 驱动更适合框架级跨包发现,lazyregistry 更适合轻量级库内使用。

AI Agent 注册系统生态对比

Nexus Registry 的定位是框架级模块发现,但 AI Agent 领域已经涌现了多种注册表方案:

维度Nexus RegistryMCP RegistryAWS Agent RegistryAgenticMesh
定位评测框架模块发现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 RegistryHarbor 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 拦住)8646%
回答旧 wire 的合计6535%(2025-11-25 占 36 / 2025-06-18 占 21 / 2025-03-26 占 5 / 2024-11-05 占 3)
回答 2026-07-28 新 wire74%
瞬时错误2815%

关键比例要连带分子分母一起读:在返回了协议版本的 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 联邦发现,构成三层递进的发现能力。