章节导航 第 12 章 / 共 21 章
Runtime Server 深度解剖
FastAPI + Socket.IO 双通道、invoke 端点、Blob sideband、Worker Venv、LLM Proxy、RPCReplayGuard
Runtime Server 是什么
Runtime Server 是运行在沙箱内部的服务——一个 FastAPI + Socket.IO 应用。它接收 Host 侧的请求,在沙箱环境中执行,返回结果。
nexus/runtime/server/app.py 是最大的单文件之一(1243 行),包含了 Server 的所有端点和逻辑。
双通道架构
Host (RemoteRuntime) Sandbox (Runtime Server)
│ │
├── HTTP ──────────────────────────► │ POST /api/v1/invoke
│ (RPC: invoke, call_tool, │ POST /api/v1/call_executor
│ call_executor, venv) │ POST /api/v1/venv
│ │
├── Socket.IO ◄──────────────────── │ emit('log', items)
│ (Events: log, span, │ emit('span', items)
│ invoke:done, venv:done) │ emit('invoke:done:{rid}', response)
│ │
HTTP 是主通道——所有 RPC 调用走 HTTP。Socket.IO 是辅助通道——推送实时日志和 Span 事件。
invoke 端点的 Long-Poll 机制
POST /api/v1/invoke
Header: Prefer: wait=30
→ 如果 30 秒内执行完毕:200 + InvokeResponse
→ 如果超过 30 秒:202 + {request_id}
→ Host 等待 SIO push event 'invoke:done:{rid}'
→ 或者 HTTP polling GET /api/v1/invoke/{rid}
这个设计平衡了延迟和资源占用:短任务直接返回,长任务异步通知。
Blob Sideband
当 payload 或 result 超过 1MB 时,不走 JSON 内联,而是通过单独的 HTTP 端点传输:
Host: POST /api/v1/blob/{blob_id} (上传大参数)
Host: POST /api/v1/invoke {payload_ref: blob_id} (引用)
Server: 执行...
Server: 200 {result_ref: result_blob_id} (大结果同理)
Host: GET /api/v1/blob/{result_blob_id} (下载)
这避免了 base64 编码大数据时的内存峰值。
Worker Venv 机制
Worker Venv 解决一个问题:如何在沙箱内运行自定义的 Python 扩展代码,同时与 Runtime Server 本身的依赖隔离。
架构
沙箱
├── Base Process (Runtime Server)
│ ├── FastAPI Server
│ ├── Executor Registry
│ └── Worker Launcher
│
├── Worker Process #1 (venv-abc)
│ ├── 独立的 Python venv
│ ├── 安装了 artifact wheel(用户的扩展代码)
│ ├── Socket.IO Client → 连接 Base
│ └── 接收 invoke 请求,执行,返回结果
│
└── Worker Process #2 (venv-xyz)
└── ...
创建流程
- Host 发送
POST /api/v1/venv,包含 artifact wheel(base64 编码)和依赖列表 - Server 的
VenvManager创建新的 Python venv(使用 BFS 闭包 symlink 复用已有包) - 安装 artifact wheel 和额外依赖
- 启动 Worker 子进程
- Worker 通过 Socket.IO 连接 Base,注册为可用 Worker
invoke 路由
# InvokeRequest.venv_id 决定去哪里执行
if request.venv_id:
# 路由到对应的 Worker 进程
worker = workers[request.venv_id]
result = await worker.invoke(request)
else:
# 在 Base 进程执行
result = await execute_locally(request)
LLM Proxy Services
Runtime Server 内置了 4 种 LLM API 代理:
| Proxy | 路径 | 用途 |
|---|---|---|
| OpenAI Proxy | /v1/chat/completions | 代理 OpenAI 格式的请求 |
| Anthropic Proxy | /v1/messages | 代理 Anthropic 格式的请求 |
| Gemini Proxy | /v1beta/models/... | 代理 Gemini 格式的请求 |
| Responses Proxy | /v1/responses | 代理 OpenAI Responses 格式 |
这些 Proxy 是 Installed Agent 的关键。当 Claude Code CLI 在沙箱里运行时,它的 API 请求会被路由到 Anthropic Proxy。Proxy 通过 Socket.IO 将请求转发给 Host,Host 使用配置的 OpenAI Client 完成推理,然后将结果返回。
这个机制实现了:
- 沙箱内不需要 API Key(安全)
- Host 侧统一做 token 计数和轨迹采集
- 可以用不同的 LLM 替换原始 Agent 的模型
LLM/MCP Proxy 治理全景
当前 Nexus 的 LLM Proxy 专注于格式转发和 token 计数,但生产环境需要三层治理能力:安全管线、成本控制、MCP 细粒度访问。下面从三层架构重构 Proxy 治理方案。
安全管线层
CrabTrap 模式(请求内容安全审查):Brex 开源的 CrabTrap 使用 LLM-as-a-judge 两阶段评估——静态规则(URL 模式匹配,微秒级)→ LLM 判断(自然语言策略,处理长尾)。Nexus 当前不做请求内容审查,恶意 prompt 可经由 Proxy 无约束地到达 LLM API。
Traefik 组合式安全管线(2026.06 发布):Traefik Hub Triple Gate 的安全管线采用多供应商并行执行模式——Regex Guard → Microsoft Presidio(PII 脱敏)→ NVIDIA NIMs(内容安全)→ IBM Granite Guardian(策略合规),每层可独立启用/替换。这种组合式架构比单一 LLM-as-a-judge 更灵活,Nexus 可借鉴此模式在 Proxy 层构建可插拔的安全管线。
OWASP Agentic Top 10 映射:Traefik 社区已将 MCP Gateway 的四层安全管线映射到 OWASP Agentic Security Top 10 风险类别。对 Nexus Runtime Server 有直接参考价值:
这份清单的正式名称是 OWASP Top 10 for Agentic Applications for 2026,由 OWASP GenAI Security Project 下属的 Agentic Security Initiative(ASI)于 2025-12-09 发布。官方描述其为”面向自主与 agentic AI 系统的最关键安全风险清单,由 100 多位行业专家、研究者与从业者协作评审而成”,并设有 Distinguished Expert Review Board,成员来自 NIST、欧盟委员会、艾伦·图灵研究所等机构。官方十项条目全称为:
ASI01 Agent Goal Hijack|ASI02 Tool Misuse & Exploitation|ASI03 Identity & Privilege Abuse|ASI04 Agentic Supply Chain Vulnerabilities|ASI05 Unexpected Code Execution|ASI06 Memory & Context Poisoning|ASI07 Insecure Inter-Agent Communication|ASI08 Cascading Failures|ASI09 Human-Agent Trust Exploitation|ASI10 Rogue Agents
| OWASP 风险(官方全称) | Traefik 管线层 | Nexus 对应状态 |
|---|---|---|
| ASI05 Unexpected Code Execution(非预期代码执行,官方示例为 AutoGPT RCE) | TBAC 阻止工具调用 | 需 Runtime Server 增强——沙箱层(Ch11)负责隔离,Proxy 层负责授权;但两层之间没有边界:沙箱内的命令与自动接受的编辑可以改写 --mcp-config 传入的 MCP 配置文件(Claude Code 2.1.309,2026-10-22 修复),改配置即改工具面与权限面 |
| ASI06 Memory & Context Poisoning(记忆与上下文投毒) | Granite Guardian hallucination+RAG | 当前无对应机制 |
| ASI07 Insecure Inter-Agent Communication(不安全的 Agent 间通信) | MCP Gateway 认证加密审计 | RPCReplayGuard 覆盖重放,但缺少 Agent 间通信的认证加密 |
| ASI08 Cascading Failures(级联失败) | Failover Router 断路器链 | 当前无断路器 |
安全管线是 Nexus Runtime Server 目前最薄弱的环节——CrabTrap/Traefik 都是外部方案,Runtime Server 本身不做请求内容审查。如果 Installed Agent 通过 Proxy 发送恶意 prompt,当前唯一的防护是模型自身的安全对齐。
⚠️ 隔离层与授权层之间不是两个独立层。 上面 ASI05 那一行把”Ch11 沙箱负责隔离、Proxy 层负责授权”写成清晰分工,实测并非如此:客户端 v2.1.309(2026-10-22)修的是”沙箱内的命令与自动接受的编辑能够改写由
--mcp-config传入的 MCP 配置文件”(官方 changelog 原文:“Fixed sandboxed commands and auto-accepted edits being able to modify the MCP config file passed with--mcp-config”)。改 MCP 配置等于同时改工具面与权限面——隔离层判定为”可写”的那次写操作,直接改写了授权层赖以决策的输入。对 Nexus 的具体要求是:MCP 配置与授权策略对沙箱内可写路径必须只读;若业务上必须允许修改,则在 Proxy 侧对配置变更做校验与审计,而不是把配置文件当作沙箱内的普通文件。同一条也适用于 ASI07:Agent 间通信若以”改对方的配置”为通道,认证加密也拦不住。
⚠️ 核对 ASI 编号时的陷阱:网络上流传着另一套与官方错位的 ASI 编号(例如把 ASI05 写成”不充分的护栏和沙盒”、ASI06 写成”敏感信息泄露”)。本书采用 OWASP 官方发布版编号,读者核对时请以官方条目全称为准,不要只比对数字——数字相同但名称不同的,不是同一条风险。
成本治理层
TokenGuard 模式(预算保护与去重):TokenGuard 实现请求去重(相同请求缓存)、token 预计算(tiktoken)、电路断路器(超限暂停)。Nexus 的 token 计数仅用于事后统计,无实时预算保护和超限断路。
LLMCap 硬上限保险丝:开源代理层,拦截所有 LLM API 调用强制执行美元硬上限,<5ms 开销,支持 OpenAI/Anthropic/Google 多供应商。相比 TokenGuard 的 token 预算,LLMCap 用美元硬上限更直观——开发者可直接设置”$50/天”而非换算 token 数。
CostGuard 多级断路器:4 层电路断路器(session/hour/day/project)、tiktoken 预估成本、Safe Mode 暂停高价请求待人工确认、实时终端仪表板。比 TokenGuard 更完善,增加了 Safe Mode 和多时间粒度预算。
RapidClaw 三层纵深防御:Layer 1 Agent(重复检测+错误率+步骤预算+冷却)、Layer 2 Service(per-agent token/hour + per-task USD cap)、Layer 3 Infra(daily tenant USD cap + 供应商月度限额 + kill-switch)。Nexus 当前仅有 Runtime Server 侧的 token 计数,缺少 Service 层和 Infra 层的预算治理。
工具级经济权重建模(budget limiting):上述四方案均以 token 或 USD 为预算单位,2026 年 MCP Gateway 治理进一步延伸出”按工具经济权重”的细粒度建模——为每个工具标注成本权重(如 search_code=1 credit、generate_report=200 credits),使 rate limiting 升级为 budget limiting。其现实动因是:一个未治理的 agent 高频调用昂贵工具(如 800 次昂贵调用)可造成数千美元的成本事故。与 RapidClaw Layer 2 的 per-task USD cap 相比,工具级建模是更细的粒度——USD cap 是任务级上限,工具权重则刻画”单次调用的相对成本”。
第五个预算维度:跨轮累积计费。 上面四个方案加工具级权重,账本的时间粒度是 session / hour / day / project / per-task,但它们计的都是”本轮新产生的 token”——没有任何一条覆盖”同一份内容在后续每一轮里被重新计费”这种跨轮累积形态。arXiv 2609.28585(2026-09-23)把它命名为 persistent billable state,并给出形式化定义与实测规模:
- 机制:多步工具调用 agent 的运行时会把外部工具返回值带进后面的模型输入,供应商因此对它再计一次费。一个已被准入的恶意或被攻陷的工具,无需受害者凭证、也无需本地运行时特权,就能把不可信数据转成”反复由受害者付费的处理”。
- 量级(均取自 abs 页,未回 HTML 正文主表):6 个模型家族、243 次执行的用量遥测显示,单次会话的累计输入最高达到该会话首次调用输入的 14,293 倍;受控的历史策略重跑把”保留原始历史”这一项的贡献单独隔离出来——平均有效会话成本上升 21.2%–35.9%。论文同时给出 6 条 DoW 攻击向量与 DOW-BENCH。
- 对压缩的判定(与 Ch15 直接相关):在依赖历史的任务上,压缩在 12 个任务里成功 10 个与 11 个(两个供应商),而删除策略只有 2 个。压缩确实能压住这条路径,但它不是”免费的正确解”——论文主张的是”确定性历史变换 + 四条宿主侧不变量”,在重新摄入之前就从提示质量、上下文增长、递归机会、累计支出四个方向设界。
对 Nexus 的含义是具体的:Runtime Server 侧的 token 计数天然能看到”本轮输入里有多少 token 是上一轮工具结果的重读”。把这个数单列成一个指标,跨轮累积成本就从不可观测量变成可观测量;否则除了压缩之外没有任何机制能抑制它,而压缩本身要等到窗口压力出现才触发。
治理组件的失败方向必须显式声明。 与上面”预算维度”并列的一条设计约束:Proxy 的每个治理插件都应带一个 on_error 策略字段,且预算/配额类组件的默认值必须是拒绝(fail-closed)。反例已在生产中修过一次——Traefik Hub v3.21.3(2026-10-15)修的是 plan middleware 在找不到 application ID 时放行请求,官方改为对无 application ID 的请求直接返 403(keyless 认证的请求除外),理由原话是 “a request that fails to resolve an application can no longer skip plan enforcement”。一个本该拦截的组件在无法判定时选择了放行,方向与 LLMCap / CostGuard / RapidClaw 三层断路器完全相反。
治理状态的存储选择:上述成本控制方案都需要持久化状态(token 计数/预算/断路器状态)。选择分布式中间件(Redis/PostgreSQL)还是嵌入式数据库(SQLite)?
2026 年 6 月的系统性基准测试表明:SQLite WAL 模式 + synchronous=FULL 可支撑 ~1,000 durable commits/sec,而 LLM Proxy 治理层的写入频率远低于此(每次 LLM 调用 <1 次状态写入,秒级间隔)。Cloudflare Workflows V2 已在生产环境验证 SQLite-backed 工作流状态存储(4,500→50,000 并发实例)。
结论:Runtime Server 内的 Proxy 治理状态用 SQLite 存储即可,无需引入 Redis/PostgreSQL。这与 Batch Runner 用 SQLite 做任务状态的设计哲学一致——简单、单文件、天然支持 resume。
MCP 治理层
转发面:不跟随重定向。 上面三层治理都假设”请求会打到配置里的那个目的地”,但转发过程本身还有一个面:HTTP 重定向。客户端 v2.1.299(2026-10-14)起做了两条改动(官方 changelog 原文):
“Changed requests to claude.ai’s connector proxy and to Anthropic-hosted MCP servers to no longer follow HTTP redirects; redirects by a connector’s own server are unaffected” “Changed MCP requests in cloud and self-hosted runner sessions to no longer follow HTTP redirects from the session’s MCP proxy”
两条都区分了被代理的那台 server 自己的重定向不受影响——放弃跟随的只是代理层自己发起的请求。对 Nexus MCP Proxy 的含义:跟随 302 等于把请求导到配置之外的目的地,与 TBAC”限制对哪些资源做什么操作”直接冲突。建议默认不跟随,并把”目标 host 是否仍在允许清单内”做成转发前的显式校验。
TBAC 细粒度访问控制:Traefik 的 Task-Based Access Control 不限制”哪个 agent 连哪个 MCP server”,而是限制”这个 agent 可以通过这个 MCP server 对哪些资源做什么操作”,配合速率限制+时间窗口+审计日志。这比章节原先提到的 CrabTrap 请求内容审查更全面——从”请求内容是否安全”升级为”操作是否在授权范围内”。
Traefik MCP Gateway:作为 Triple Gate 的一部分,提供 MCP 工具调用的统一治理入口。Nexus 当前缺少 MCP 调用的治理层——Installed Agent 通过 MCP 调用外部工具时,既无速率限制也无操作审计。
MCP server 自身也会出事故:前面讨论的隔离问题源自宿主应用侧,而 CVE-2026-32211(Microsoft 披露,NVD 于 2026-04-03 收录)是 Azure MCP Server 关键功能缺失认证——未授权攻击者可经网络获取信息。需注意该 CVE 的 CVSS v3.1 评分存在两个来源:9.1(CRITICAL,向量
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N)与 7.5(HIGH,…/C:H/I:N/A:N),分歧在于是否计入完整性影响,引用时应标注这一分歧而不是二选一。
它与 Ch11 提到的 CVE-2025-59528(Flowise CustomMCP 节点 RCE,CVSS 10.0)恰好互补:后者是宿主应用解析用户提供的 MCP 配置不当、导致宿主机被 RCE;前者是 MCP server 自身压根没有认证。对本章的治理论证而言,Flowise 那条说明”不能让 MCP 工具直接在宿主上执行”,Azure 这条则说明”连认证都没有的 server 会被直接挂到互联网上”——TBAC 与审计日志要防的不只是越权调用,还包括这种默认开放。
⚠️ 即便有认证、即便用户批准了,粒度仍然不对——这是 TBAC 的第三个论据。 前两条 CVE 分别说明”不能让 MCP 工具直接在宿主上执行”与”连认证都没有的 server 会被挂到互联网上”,都还停留在”有没有访问控制”。arXiv 2610.22301(2026-10-15)指出的是下一层:在典型的本地部署中,客户端批准一次工具调用,是把宿主文件系统的宽泛权限授予了 server 进程,而不是限制在该工具声明的操作上。论文把这个漏洞类别命名为 filesystem capability laundering——攻击者引导的参数可以让一个工具访问其声明契约与部署范围之外的宿主敏感文件。
它在三层上做了规模化检测(L1 server 类目筛查 / L2 每工具契约分析 / L3 可绕过路径校验),规模如下(均取自 abs 页,未回 HTML 正文主表):跨 9 个 registry 的 21,097 个 MCP server,在 4,806 个进入分诊的 server 中 787 个(16.4%) 虽被归类为非文件系统类功能,却实际具备文件系统能力;动态三例校验在受测沙箱策略下确认 150 个可利用实例;协同披露产出 13 条安全公告,含 Anthropic Git MCP Server 的两个 CVE。
这条把 TBAC 的必要性从”要有访问控制”推进到”访问控制的粒度必须匹配工具声明的契约,而不是进程边界”。对 Nexus MCP Proxy 的落点:授权决策的最小单位应是
(server, tool, 参数路径)三元组,而(server, 进程)这种粒度等于没有粒度。
⚠️ 两条不吃配置的硬边界(客户端实测,2026-09,均取自官方 changelog 一手):
- 约 5 分钟的硬超时——Streamable HTTP 的 MCP 工具调用存在一条不受 per-server
timeout控制的超时上限,即使把 per-server timeout 设得更长也会生效(Claude Code 2.1.274,2026-09-17 修复)。- 2048 字符上限——MCP 工具描述与 server 指令默认有 2,048 字符上限(2.1.280,2026-09-22 起可用
CLAUDE_CODE_MAX_MCP_DESCRIPTION_LENGTH调整)。二者的共同点是配置写了但不生效,且没有报错。这对 Proxy 层尤其危险:工具描述被截断后,基于描述做匹配的策略(TBAC / 审计 / 预算分级)会表现为”策略没配”,而不是”描述被截断”——排查方向完全不同。因此 Proxy 若要做工具治理,必须先把这类上限显式暴露出来。
MCP 2026-07-28:协议无状态化对 Proxy 架构的影响
MCP 协议 2026-07-28 版本(2026-05-21 发布 RC,7/28 正式)是协议史上最大修订。对 Nexus Runtime Server 的 LLM/MCP Proxy 有以下直接影响:
简化 Runtime Server 的 MCP 代理逻辑:
- 旧协议:Runtime Server 需维护 Mcp-Session-Id → worker 的映射,支持 sticky session 以保持 MCP 连接。session 断开重连需恢复状态。
- 新协议:移除 initialize 握手和 Mcp-Session-Id。每个
tools/call请求自包含(clientInfo 在_meta中传递),任意 Runtime Server 实例可处理。不再需要 sticky routing。
提升 MCP 治理层的能力边界:
Mcp-Method+Mcp-Nameheader 使 Traefik MCP Gateway 可基于 header 路由,无需解析 body。速率限制/审计可在 LB 层实现,无需应用层介入。ttlMs缓存(SEP-2549)使tools/list结果可被 Proxy 缓存,减少重复的server/discover调用。但缓存只是一半——另一半是对list_changed的速率限制:server 若高频发送list_changed通知,客户端会陷入持续的tools/list重取与高 CPU(客户端实测修复于 2026-09-14,Claude Code 2.1.271)。只做 TTL 缓存而不对通知做限流,缓存与通知会构成正反馈回路,Proxy 反而被动放大流量。- Multi Round-Trip Requests(SEP-2322)替代 SSE 流——对
tools/call、resources/read、prompts/get三类请求(规范明确:其他请求一律不得返回该结果),服务端可返回resultType: "input_required"的InputRequiredResult,且必须至少携带inputRequests或requestState之一。inputRequests是服务端发起的请求映射(键由服务端分配、须在本次请求内唯一,值只能是ElicitRequest/CreateMessageRequest/ListRootsRequest);requestState是对客户端不透明的字符串。客户端收集输入后,用新的 JSON-RPCid(规范要求与首次请求不同,因为两者是独立请求)重试原方法,回传inputResponses;收到过requestState就原样回显,没收到则不得凭空补一个。elicitation 因此不再需要持久连接,服务端也不再主动向客户端发请求,这消除了 Proxy 层的连接管理复杂性。
⚠️ elicitation 另有 URL 模式,且它带来一个反向破坏。 在 2026-07-28 协议上,elicitation 新增 URL 模式——服务端可以要求客户端打开一个浏览器流程(用于登录等),客户端侧实现为”服务端无法确认完成时不在屏幕上留下等待对话框”(Claude Code 2.1.281,2026-09-23)。同一能力在旧协议(2025-11-25)上的落地方式不同:客户端为支持 URL prompts 引入了新的配置要求,未声明
"bareElicitationCapability": true的 server 会直接连不上(2.1.287,2026-10-01)。这与上面”迁移窗口内旧实现仍可工作”的乐观预期相反:协议能力升级会以”连不上”的形式反向破坏旧 server,且报错不指向根因。Nexus 的 MCP Proxy 若要在窗口期内同时服务新旧 server,须显式枚举这类 capability 声明,而不是只做版本协商。
⚠️ 这不是 elicitation 独有的问题,而是”能力声明”这一族问题的第一例。 客户端 v2.1.302(2026-10-16)修的是:server 协商了 2026-07-28 却省略
resultType/ttlMs/cacheScope时,客户端侧表现为”零工具”或”每次调用都失败”(官方 changelog 原文:“Fixed MCP servers showing no tools, or every tool call failing, when the server negotiates protocol version 2026-07-28 but omitsresultType,ttlMsorcacheScope”)。这三个字段正是本节上下两面在讲的东西——MRTR 的
resultType、SEP-2549 的ttlMs、以及缓存作用域。也就是说:声明了新版本而不带新字段,比留在旧版本更糟。对 Nexus 的落点因此可以更具体:Proxy 若要同时服务新旧 server,应维护一张”声明版本 → 必带字段”清单,缺字段时给出指向根因的报错(“server 声明 2026-07-28 但未提供ttlMs”),而不是让下游把故障读成”这个 server 没有工具”——后者会把排查方向整体带偏。同一族的第三条:v2.1.299 起 MCP allow 规则的匹配粒度也变了——
mcp__a不再放行名为a__b或a_的 server,须写成mcp__<server>__*并写全规范化名。授权规则的名字匹配同样属于”声明族”问题。
- ⚠️ 但 Proxy 不能把
requestState当透明字节:规范要求服务端把requestState视为攻击者可控输入——若它影响授权、资源访问或业务逻辑,服务端必须做完整性保护(HMAC 或 AEAD),并应在受保护载荷内放入防重放字段。对 Nexus Runtime Server 的 MCP Proxy 而言,这一点比”少管理几条连接”重要得多:Proxy 若只做透传,等于把一个可被篡改的授权凭据暴露在链路上,与本章RPCReplayGuard要防的重放属于同一类问题。
CIMD 身份模型对安全管线的影响:
- DCR 被 CIMD 替代——Installed Agent 的 MCP 客户端身份由域名托管的元数据文档证明,而非运行时注册。这意味着 Traefik TBAC 策略中的 Agent 身份可绑定到域名而非动态 token。
迁移窗口:正式规范 2026-07-28 发布,向后兼容迁移窗口为 12 个月,至 2027-07-28 截止(Roots/Sampling/Logging/DCR 等弃用项同属此窗口)。以本书当前时间点(2026-09)计,发布至今约七周,适配工作仍处于窗口期的前 15%。现有 sticky session 逻辑在新协议下已成为死代码,移除可简化 Proxy 代码量。
窗口进度改用可复查的锚点,不用百分比。 上面”发布至今约七周、处在前 15%“是按写作时点算的,会随时间失效。换成两个可直接复核的事实(核于 2026-10-24):
- 客户端侧已把新协议设为默认:v2.1.299(2026-10-14)起,云端会话与 Remote Control 的 MCP 连接器在不拉取任何 flag 的安装上默认协商 2026-07-28(
MCP_PROTOCOL_NEGOTIATION=legacy可退出)。也就是说迁移窗口过了一个半月,主流客户端已经从”支持新协议”走到”默认用新协议”。- 网关侧也已完成切换:Traefik Hub 的兼容矩阵显示,v3.21.3 起列出的是
MCP specification 2026-07-28,而 v3.20.16 仍是2025-06-18。本章对标的基础设施层方案已经站到新协议上。二者合起来的结论是:“旧实现仍可工作”的窗口实际比 12 个月短得多——客户端默认切到新协议之后,旧 server 面对的不再是”兼容”,而是上面两条那种”连不上 / 零工具”的反向破坏。
Logging 弃用与 trace context 标准化对治理审计的影响:MCP 7/28 同时弃用协议级 Logging(SEP-2577,12 个月移除窗口),改由 stderr + OpenTelemetry 承担结构化可观测性,并标准化 W3C trace context(traceparent/tracestate/baggage)。对 Nexus Runtime Server 的 Proxy 治理层意味着:审计日志可直接对接 OTel Collector,而非维护私有 MCP 日志格式;trace context 的标准化也使 Proxy 层的请求追踪能与 MCP server 内部 spans 无缝关联。
无状态化的代价面:无状态消除了 sticky routing,但没有消除客户端侧的会话级状态。实测中,一个无状态远端 MCP server(典型场景:网关/代理正在重新部署)只要短暂返回一次 HTTP 404,客户端就会在本次会话剩余时间内把它判为不可用,而界面仍显示”已连接”(Claude Code 2.1.283,2026-09-25 修复)。
对 Nexus MCP Proxy 的含义:Proxy 侧必须区分”server 已连接”与”server 可用”两个状态,并对瞬时 4xx/5xx 做独立的健康判定与恢复,不能让一次抖动把整场会话钉死。这与本章 RPCReplayGuard 要防的问题属于同一族——都是”连接层看起来正常、语义层已经坏了”。
Agent-Aware 优雅错误处理
传统网关拦截返回 HTTP 403 会中断 agent 多步工作流——ReAct 循环被强制打断后,agent 无法恢复上下文继续执行。Traefik 和 RapidClaw 均采用更优雅的模式:返回 HTTP 200 + schema-compliant 拒绝消息,agent 可理解拒绝原因并调整策略继续运行。
对 Nexus 的启示:Runtime Server 的 LLM Proxy 拦截恶意请求或超限请求时,应返回结构化拒绝消息(如 {"error": "budget_exceeded", "remaining_budget": 0, "suggestion": "use_compact_model"}),而非直接 HTTP 403。这使 Installed Agent 的 ReAct 循环不被打断,可降级到更经济的模型继续运行。
与 OpenHands Action Execution Server 的对比
OpenHands 的 Action Execution Server 是 Nexus Runtime Server 的直接对标方案,核心差异:
| 维度 | Nexus Runtime Server | OpenHands Action Server |
|---|---|---|
| 框架 | FastAPI + Socket.IO | FastAPI(单端点) |
| 端点设计 | 多端点(/invoke + /call_executor + /venv) | 单一 /execute_action |
| 插件系统 | 无 | VSCode / Jupyter / AgentSkills |
| OOM 防护 | 无 | 内存监控 + 主动 kill |
| MCP 集成 | 无内置 MCP proxy | MCP proxy manager |
| Worker 隔离 | VenvManager + BFS 闭包复用 | 无(单进程执行) |
| 大 payload | Blob Sideband(独立端点) | 无特殊处理 |
设计权衡:
- Nexus 的多端点设计提供了更细粒度的控制(invoke vs call_executor vs venv),但增加了 API 复杂度
- OpenHands 的单一端点更简洁,但灵活性受限
- OpenHands 的OOM 防护是 Nexus 缺少的重要特性——当 Agent 执行失控消耗内存时,Nexus 缺少主动检测和恢复机制
与 Traefik Hub Triple Gate 的对比
Traefik Hub Triple Gate(API Gateway + AI Gateway + MCP Gateway)是基础设施层的生产级方案,Nexus Runtime Server 则是应用层代理,两者定位不同但功能重叠:
| 维度 | Nexus Runtime Server | Traefik Hub Triple Gate |
|---|---|---|
| 治理范围 | 仅 LLM 代理 | LLM + MCP + API 统一治理 |
| 安全管线 | 无内置 | 多供应商并行(Presidio/NIMs/Granite Guardian) |
| 成本控制 | Token 计数(事后统计) | Token 配额 + USD 上限 + 多级断路器 |
| 容错路由 | 无 | 多供应商 failover |
| Agent-Aware 错误 | 无 | 200 + 结构化拒绝 |
| MCP 访问控制 | 无 | TBAC 细粒度 + 审计日志 |
| 部署形态 | 沙箱内 FastAPI | K8s Helm / 独立网关 |
| Token 限速 | 无 | per-user/team/endpoint |
关键差异:Traefik 覆盖范围更广但定位于基础设施层,Nexus 定位于应用层但拥有更深的 Agent 运行时上下文(如 Socket.IO 事件流、Worker Venv 状态)。理想的架构是两者协同——Traefik 在基础设施层治理 LLM/MCP/API 流量,Nexus 在应用层利用运行时上下文做更精细的 Agent 行为治理。
除 Traefik 外,2026 年 MCP Gateway 生态已扩展为多方案竞争格局。下表六项的仓库归属、许可证与官方一句话定位已于 2026-09-15 直连 GitHub 核实(star 数为同期快照):
| 方案 | 官方仓库 | 许可证 | 官方一句话定位 |
|---|---|---|---|
| Docker MCP Gateway | docker/mcp-gateway | MIT | docker mcp CLI 插件 / MCP Gateway;目录中的本地 MCP server 各自跑在独立隔离容器里,npx/uvx server 只授予最小宿主权限,密钥经 Docker Desktop secrets 管理而非环境变量 |
| IBM ContextForge | IBM/mcp-context-forge | Apache-2.0 | 位于 MCP / A2A / REST-gRPC API 之前的 AI Gateway、registry 与 proxy——即不必重写就能把既有 REST/gRPC 内部 API 暴露为 MCP 工具 |
| Microsoft MCP Gateway | microsoft/mcp-gateway | MIT | MCP server 的反向代理与管理层,面向可扩展、安全的部署 |
| Lasso MCP Gateway | lasso-security/mcp-gateway | MIT | 插件化网关,用于编排其他 MCP server |
| Obot | obot-platform/obot | MIT | 完整的 AI 治理平台 |
| Kong AI Gateway | Kong/kong | Apache-2.0 | ”The API and AI Gateway”——MCP 流量以插件形式叠加在既有成熟网关之上 |
⚠️ 表中”官方一句话定位”取自各仓库 GitHub 首页自述,属一手来源;但各类横评中流传的更细的能力描述(如 Microsoft 侧的 Entra ID RBAC 与会话感知路由、Lasso 侧的 prompt injection 实时检测与 server 信誉扫描、Obot 侧的 hub-and-spoke 控制平面、ContextForge 侧的多集群联邦治理)本轮未能从官方文档逐项证实,仍按待核实处理,请勿与表中已核实信息混用。
另需更正一处常见误传:Docker MCP Gateway 的许可是 MIT,不是部分资料所写的 Apache 2.0。
活跃度分档(gh api repos/... 与 .../releases 直取,核于 2026-10-24):
| 方案 | star | 最近 release | 最后 push | 判读 |
|---|---|---|---|---|
| Docker MCP Gateway | 1,613 | v0.44.2 / 2026-10-21 | 2026-10-21 | 活跃,版本仍在 0.x |
| IBM ContextForge | 4,685 | v1.1.0 / 2026-10-20 | 2026-10-23 | 已过 1.0 |
| Microsoft MCP Gateway | 894 | 无 release | 2026-10-21 | 活跃,从未发版 |
| Lasso MCP Gateway | 395 | v1.2.0 / 2026-01-21 | 2026-01-22 | ⏸️ 停更 9 个月,不应与其余五家并列为活跃竞争者 |
| Obot | 1,120 | v0.28.0-alpha3 / 2026-10-22 | 2026-10-23 | 活跃,但仍在 alpha |
| Kong | 44,296 | 3.9.4 / 2026-10-12 | 2026-10-19 | 活跃(star 数为整个 Kong 网关,非 MCP 插件部分) |
Lasso 单独标注是本轮最重要的一处修正:把它与其余五家并列会误导读者。它自 2026-01-22 起零提交、最新 release 停在 2026-01-21,而本章下文把它列为”Lasso 的安全向编排”选型参考——选型前应确认该项目仍在维护。同理,Microsoft MCP Gateway 至今没有任何 release,Obot 仍在 alpha;两者可作为方向参考,但不宜当作已可投产的对标物。上表 star 数也替代了 2026-09-15 的旧快照。
用一条可核查的分类轴替代逐项核能力。 上面四条”待核实”的能力描述挂了两个月仍未解决,原因是逐项核厂商自述本来就低效。arXiv 2610.23449(2026-10-16)的 GatewayBench 提供了更快的路径——它是第一个统一的 MCP 网关评测框架与基准:524 个任务、6 个领域、工具池含 251 个真实 MCP server 的 11,118 个工具,并在 7 个已广泛部署的 MCP 网关上跑了良性与对抗性两类任务,结论是网关设计在任务完成率、工具使用效率、抗攻击性上差异显著,且与底层模型和 agent harness 强交互。
它给出的主分类轴是 flattened(扁平暴露全部工具)vs hierarchical(分层聚合后再暴露)。本章六家表可以沿这条轴重排,这比逐项核能力描述更快,也更可核查。
⚠️ 不要把 GatewayBench 的结果当成上面四项”待核实”描述的证实。 论文摘要未逐项点名厂商能力,本轮也未读正文确认其是否覆盖本章这六家;它只能提供分类轴与评测方法,不能替代厂商一手文档。(数字均取自 abs 页,未回 HTML 正文核。)
其中 Docker MCP Gateway 值得单独点出:本书 Ch10/Ch11 把 Docker Sandboxes 作为重要沙箱方案讨论,而同一家厂商在网关层另有这款独立产品。做网关选型时若只对标 Traefik,就会漏掉与沙箱层同源的这一层——它的定位也确实偏开发者本地与容器原生,跨团队统一策略仍需另加工具。
同一现象在 Traefik 身上以相反的形式出现。 2026-10-22,Traefik Labs 发布了 Traefik MCP Server(厂商新闻稿,SAN FRANCISCO, October 22, 2026)——一款只读 MCP server,同时把三样东西喂给 agent:① 什么是合法的,取自所部署那个 Traefik 版本的精确 schema;② 什么在跑,取自网关的实时配置;③ 发生了什么,取自 Datadog、Grafana 栈(Prometheus / Tempo / Loki)或 Dash0 的 trace / metric / log。GA 于 Docker Hub 与 GitHub Container Registry,需 Traefik Hub 授权 token 解锁;解锁后同时读 Traefik Proxy 与 Traefik Hub 网关。官方原话:“Having an MCP server is not the news. What an agent can do with it is.”
也就是说,网关厂商的方向不是二选一,而是两层都占:Docker 在网关层另有一款独立产品,Traefik 则把网关本身做成 MCP server。对 Nexus 的选型对标而言,这意味着”Nexus 拥有更深的 Agent 运行时上下文”这条优势,要与”网关厂商正在把配置与遥测也做成 MCP 可消费”同时评估——后者恰好补的是 Nexus 不掌握的那一半(基础设施层的真实拓扑与历史信号)。
另有一处同期进展可作为本章 §安全管线层 的更新线索(待核 📌):Traefik Hub 的 MCP Gateway Guards 已进入 Early Access,允许把 Content Guard / LLM Guard / Parallel LLM Guard 串在 MCP middleware 之后,对双向的 MCP 工具调用做扫描(到达 server 前的参数、返回客户端前的结果),覆盖 buffered JSON 与 SSE 两种传输。官方 release notes 未标明该能力对应的最低版本与 GA 时间,引用前须回官方文档核一轮。
这些方案与 Traefik 形成”通用网关 vs 专用安全 vs 协议桥接”的定位差异——Nexus Runtime Server 在选型对标时不必局限于 Traefik 一家,可按需借鉴 Kong 的插件化、Lasso 的安全向编排、ContextForge 的 REST/gRPC 桥接等特性。
SIOBridge
Worker 进程的 Socket.IO 是 AsyncClient,Base 进程的是 AsyncServer——两者的 API 不同。SIOBridge 提供统一接口,使 Proxy 代码可以在 Base 和 Worker 中复用。
RPCReplayGuard
防止 Socket.IO 连接断开重连后重复执行已完成的 RPC:
class RPCReplayGuard:
_completed: dict[str, InvokeResponse] # 已完成的 request_id → response
def should_skip(self, request_id) -> InvokeResponse | None:
return self._completed.get(request_id)
def mark_done(self, request_id, response):
self._completed[request_id] = response
⚠️ 重连不是唯一的重复执行来源。 客户端实测中另有一条完全不同的路径:远端 MCP server 的返回结果超过 16 MB 或无法解析时,工具调用会被重试一次,从而实际执行两次(Claude Code 2.1.288,2026-10-02 修复)。这条与连接状态无关,上面的
_completed字典防不住——它防的是”重放同一request_id”,而大结果场景下的重试可能携带新的request_id。对 Nexus 的含义:Blob sideband 解决的只是传输效率,不等于幂等。本章 §Blob Sideband 把超过 1 MB 的数据挪到独立端点,与该阈值问题同源;若
result_ref指向的结果在写回前失败,重试同样会重跑一次 Executor。建议在设计层面把”已执行”标记与大结果传输分开考虑。(Nexus 侧是否已有该保护需对照源码核实 📌——此为编辑推断,非已核实事实。)另注意与 Ch13 的分工:Ch13 §持久化的边界 讨论的是”run 级重试重复副作用”,本条是”单次调用内因响应体过大重复执行”。两处应互相引用,否则读者会以为幂等问题只出现在重试路径上。
⚠️ 断连是第三条独立路径,而官方的解法不在 request_id 上。 v2.1.307(2026-10-21)修的是”HTTP MCP 工具调用在连接中途关闭时被发送两次”,官方 changelog 原文:
“Fixed HTTP MCP tool calls being sent twice when the connection closed mid-call; only read-only or idempotent tools are now retried”
关键在于修复方式:官方没有去掉重试,也没有加幂等键,而是给重试加了一道门——只有标注为只读或幂等的工具才允许重发。也就是说,判定权从”这个
request_id出现过没有”移到了”这个工具允不允许重发”。这把上面两条路径(重连、大响应)共同的困境说清楚了:三条路径都不经过
_completed字典,因此幂等判定必须与request_id去重解耦。对 Nexus 的落地形态也比”全局幂等键”轻:在ToolExecutor/ Executor 注册处加一个幂等性标注字段,RPCReplayGuard之外再配一层”重试前查该工具是否声明可重发”。未标注的工具默认不可重发——这与本章成本治理层新增的 fail-closed 约定是同一条原则。同一版本还有一条同源现象可作旁证:v2.1.299(2026-10-14)修了”headless 与 SDK 会话中的 MCP 工具调用,在后台重连关掉了它正在跑的连接时,有时失败、有时运行两次”。三条路径分属不同的连接层事件(重连 / 响应体过大 / 后台重连),但都产生”执行两次”——这说明”重复执行”是传输层的常态,而不是某一处实现的 bug。
⚠️ 治理配置的语义会在升级中静默放宽。 v2.1.305(2026-10-20)改了 allowlist 的过滤范围(官方 changelog 原文):“Changed
allowedMcpServersto stop filteringmanaged-mcp.jsonstdio servers that use${VAR}only inenv: one your allowlist left out now loads on upgrade; usedeniedMcpServersto keep it off”。含义是:升级会把此前被 allowlist 排除掉的 server 加载进来——默认方向从”不加载”变成”加载”,要维持原行为得改用deniedMcpServers。这与本章 §MCP 治理层 用 CVE-2026-32211 论证的论点同源,但方向更直接:那里是”默认没认证”,这里是”默认放行”——都不是配错,是语义变了。对 Nexus 的含义:allow/deny 清单的语义变更必须走显式迁移说明,不能靠升级静默生效;且 Proxy 侧应对”本次启动加载了哪些 server”输出一份可 diff 的清单。