













name: MCP Dual Era Support
overview: 在 carbon-apimgt 中让网关北向(客户端↔网关)与南向(网关↔MCP 后端)同时支持 MCP 1.0(2025-06-18,有会话)与 MCP 2.0(2026-07-28,无状态),并在客户端与后端协议世代不一致时由网关做转译。
todos:
当前实现锁定 MCP 1.0 Streamable HTTP(2025-06-18):
initialize + params.protocolVersion 校验;回复版本写死;Mcp-Session-Id 仅 CORS expose,不签发/校验SERVER_PROXY 大多透传;MCPInitializerAndToolFetcher 写死 initialize→session→tools/listMCPServerDTO.protocolVersion 已落 AM_API_METADATA,但运行时未使用目标:同一网关实例对 MCP 1.0 与 2.0 客户端、1.0 与 2.0 后端均可工作;南北协议可不同,由网关转译。
flowchart LR Client10[MCP1_Client] Client20[MCP2_Client] GW[Gateway_DualEra] BE10[Backend_MCP1] BE20[Backend_MCP2] Client10 --> GW Client20 --> GW GW -->|"legacy dialect"| BE10 GW -->|"modern dialect"| BE20
协议世代约定(本方案固定):
2025-06-18(initialize + Mcp-Session-Id)2026-07-28(无握手/无会话;_meta;server/discover;Mcp-Method / Mcp-Name)配置模型(固定): 每个 MCP Server 的 metadata.protocolVersion 表示 南向后端 协议;北向按请求自动探测(header / method / _meta / initialize),写入 MessageContext,再与后端版本比较决定透传或转译。
APIConstants.MCP
PROTOCOL_VERSION_2026_JULY = "2026-07-28"SUPPORTED_PROTOCOL_VERSIONS = [2025-06-18, 2026-07-28]METHOD_SERVER_DISCOVER = "server/discover"HEADER_MCP_METHOD = "Mcp-Method"、HEADER_MCP_NAME = "Mcp-Name"protocolVersion 必须属于上述集合;默认仍 2025-06-18(兼容现网)
PublisherCommonUtils、APIMappingUtil、OpenAPI publisher-api.yamlMCP-Protocol-Version / Mcp-Session-Id 基础上,强制 allow/expose Mcp-Method、Mcp-Name核心文件:McpInitHandler、MCPUtils、MCPPayloadGenerator、McpMediator
MCPProtocolNegotiator)
method=initialize 或存在 Mcp-Session-IdMCP-Protocol-Version: 2026-07-28,或 body _meta.protocolVersion,或 Mcp-Method,或 server/discoverMessageContext:MCP_PROTOCOL_VERSION、MCP_PROTOCOL_ERAMcp-Method 头,回退 JSON-RPC method;保证 throttle/auth/analytics 与 2.0 头驱动一致ALLOWED_METHODS + processInternalRequest
server/discover(网关自建 MCP 时返回 capabilities / serverInfo,替代 2.0 握手)initialize / notifications/initialized 流程tools/list / tools/call / server/discover(不要求先 initialize)validateInitializeRequest / getInitializeResponse
isNoAuthMCPRequest)
server/discover 纳入与 initialize 同级策略(本方案:需认证,与 tools/list 一致,避免未授权探测;若产品要求公开 discover,可再改配置开关)Mcp-Session-Id 响应头;后续 POST/GET 可选携带(本方案:不强制校验粘滞,但透传/存储到 context 供南向 1.0 使用)Mcp-Session-Id/mcp
DIRECT_BACKEND / EXISTING_API)
tools/list、tools/call 结果形状按北向 era 输出;2.0 列表可带 ttlMs/cacheScope 等字段(有则填,无则省略)-32002→-32602 仅对 modern)改造 MCPInitializerAndToolFetcher:
protocolVersion 参数(来自校验请求或已存 metadata)Mcp-Session-Id → notifications/initialized → tools/list + MCP-Protocol-VersionMCP-Protocol-Version: 2026-07-28 + Mcp-Method;用 server/discover(若后端支持)或直接 tools/list;body 带 _meta;不依赖 sessionMcpServersApiServiceImpl / RestApiPublisherUtils)写入探测到的实际版本到 metadata.protocolVersionSERVER_PROXY 运行时MCP-Protocol-Version、Mcp-Session-Id(1.0)、Mcp-Method/Mcp-Name(2.0)、以及 JSON body _metaprotocolVersion 注入 MessageContext(需确认 keymgt API 实体是否带 metadata;若无,在网关 DataHolder/部署产物中补充 protocolVersion 字段)tools/list 仍可由网关用已发布目录合成(保持现行为)MCPProtocolTranslator)| 北向 | 南向 | 行为 |
|---|---|---|
| 1.0 | 1.0 | 透传 |
| 2.0 | 2.0 | 透传 + 补齐 Mcp-Method/_meta(若客户端未带) |
| 1.0 | 2.0 | 吃客户端 initialize(网关本地应答);南向去掉 session,改写为 modern 请求;响应回写为 1.0 JSON-RPC |
| 2.0 | 1.0 | 网关代持后端 session(initialize + 缓存 sessionId);对客户端隐藏 session;南向发 legacy,北向回 modern |
Session 缓存:按 apiId + clientCredential/hash 短 TTL 内存/Redis(本方案优先 本地 Guava/Caffeine 式缓存 + TTL,与现有 gateway 缓存模式对齐;多节点后续再上分布式)。
DIRECT_BACKEND / EXISTING_API 的 tools/call→REST 与 MCP 版本无关;仅保证北向应答符合客户端 era(Phase 1)。
ThrottleHandler:继续仅对 tools/call 限流;method 来源含 Mcp-MethodMCP_PROTOCOL_VERSION / era / sessionId(legacy)到 SynapseAnalyticsDataProvider custom propsAPIKeyValidator:tool→resource 映射不因 era 改变iss 的更严校验不破坏现有 metadata 响应| 场景 | 期望 |
|---|---|
| 1.0 客户端 → 自建 MCP | initialize/list/call 成功,带回 session 头 |
| 2.0 客户端 → 自建 MCP | 无 initialize;discover/list/call 成功;无 session |
| 1.0 客户端 → SERVER_PROXY 1.0 后端 | 透传成功 |
| 2.0 客户端 → SERVER_PROXY 2.0 后端 | 透传成功 |
| 1.0 客户端 → SERVER_PROXY 2.0 后端 | 转译成功 |
| 2.0 客户端 → SERVER_PROXY 1.0 后端 | 转译成功(网关代持 session) |
| Publisher 拉 1.0 / 2.0 工具列表 | 各自路径成功并写入正确 protocolVersion |
| 不支持版本 | initialize/_meta 返回 supported 列表错误体 |
单测重点:MCPUtils 协商/校验、MCPProtocolTranslator 往返、MCPInitializerAndToolFetcher 双路径、Throttle method 头解析。
APIConstants.java — 版本/方法/头MCPProtocolNegotiator + MCPProtocolTranslator(gateway 包下)McpInitHandler.java / MCPUtils.java / MCPPayloadGenerator.java / McpMediator.javaMCPInitializerAndToolFetcher.java + Publisher validate/create/refresh 调用链APIMappingUtil / CORS / metadata 校验不在本清单:Helm chart、Devportal UI 大改、完整 MCP Apps/Tasks 扩展(仅保证 core tools/list/call/discover/initialize)。
靠的是 MCP Server 上配置的 protocolVersion(表示南向后端协议),不是每次请求去猜后端。
创建/更新时写入
Publisher 在 MCP Server DTO 里带 protocolVersion:
2025-06-18 → 后端是 MCP 1.02026-07-28 → 后端是 MCP 2.02025-06-18落库
写到 AM_API_METADATA,key 为 protocolVersion。
部署到网关
打进 Gateway 部署产物的 additionalProperties,运行时挂到 keymgt API.protocolVersion / apiProperties。
请求时读取
MCPProtocolNegotiator.resolveBackendProtocolVersion(api) 读这个字段,写入 MCP_BACKEND_PROTOCOL_VERSION,再和北向探测到的客户端版本比较,决定透传还是转译。
flowchart LR Pub[Publisher配置protocolVersion] DB[AM_API_METADATA] Deploy[Gateway部署产物] Runtime[Negotiator读后端版本] Pub --> DB --> Deploy --> Runtime
| 方向 | 怎么知道版本 |
|---|---|
| 北向(客户端→网关) | 自动探测:initialize / Mcp-Session-Id / MCP-Protocol-Version / _meta / Mcp-Method / server/discover |
| 南向(网关→后端) | 配置驱动:读该 MCP Server 的 metadata.protocolVersion |
protocolVersionvalidateThirdPartyMCPServer);成功后建议把对应版本写回该 Server 的 protocolVersion结论: 网关“知道”后端是几,是因为你(或校验流程)把它记在 MCP Server 配置里,并随部署带到网关;运行时只读配置,不做握手探测。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。