AIGC标识 wso2-apim-mcp2改版分析

结论

  • apim中rest实现的mcp,不需要更新2.0,它是不为2.0取决于客户端和后端服务
  • apim中mcp实现的mcp-server,需要有版本控制,版本不对,会出现问题
  • apim中的服务,如果中间走了聚合mcp服务,它返回的mcp版本取决于聚合服务的mcp版本

name: MCP Dual Era Support
overview: 在 carbon-apimgt 中让网关北向(客户端↔网关)与南向(网关↔MCP 后端)同时支持 MCP 1.0(2025-06-18,有会话)与 MCP 2.0(2026-07-28,无状态),并在客户端与后端协议世代不一致时由网关做转译。
todos:

  • id: phase0-constants
    content: 扩展 APIConstants.MCP(2026-07-28、server/discover、Mcp-Method/Name);Publisher 校验 protocolVersion;CORS 增加新头
    status: pending
  • id: phase1-negotiate
    content: 实现北向协议探测(Negotiator),写入 MessageContext;支持 Mcp-Method 与 _meta
    status: pending
  • id: phase1-handlers
    content: 改造 McpInitHandler/MCPUtils/MCPPayloadGenerator/McpMediator:dual-era initialize/discover、session 策略、GET /mcp 行为
    status: pending
  • id: phase2-fetcher
    content: MCPInitializerAndToolFetcher 按 protocolVersion 走 1.0 session 或 2.0 无状态发现,并回写 metadata
    status: pending
  • id: phase2-proxy-translate
    content: SERVER_PROXY:元数据注入后端版本 + MCPProtocolTranslator 四象限透传/转译 + legacy session 缓存
    status: pending
  • id: phase3-crosscut
    content: Throttle/Analytics/APIKeyValidator/CORS 对齐双协议 method 与版本字段
    status: pending
  • id: phase4-tests
    content: 补齐协商/转译/Fetcher/限流单测与南北向 6 类验收场景
    status: pending
    isProject: false

MCP 1.0 / 2.0 南北向双协议支持任务清单

背景与目标

当前实现锁定 MCP 1.0 Streamable HTTP(2025-06-18

  • 北向:强制 initialize + params.protocolVersion 校验;回复版本写死;Mcp-Session-Id 仅 CORS expose,不签发/校验
  • 南向:SERVER_PROXY 大多透传;MCPInitializerAndToolFetcher 写死 initialize→session→tools/list
  • MCPServerDTO.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

协议世代约定(本方案固定):

  • Legacy / MCP 1.0 = 2025-06-18(initialize + Mcp-Session-Id
  • Modern / MCP 2.0 = 2026-07-28(无握手/无会话;_metaserver/discoverMcp-Method / Mcp-Name

配置模型(固定): 每个 MCP Server 的 metadata.protocolVersion 表示 南向后端 协议;北向按请求自动探测(header / method / _meta / initialize),写入 MessageContext,再与后端版本比较决定透传或转译。


Phase 0 — 协议常量与元数据

  1. 扩展 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"
    • 增加 era 辅助常量 / 判定方法名(legacy vs modern)
  2. Publisher 校验:创建/更新 MCP Server 时 protocolVersion 必须属于上述集合;默认仍 2025-06-18(兼容现网)
  3. CORS:在现有 MCP-Protocol-Version / Mcp-Session-Id 基础上,强制 allow/expose Mcp-MethodMcp-Name

Phase 1 — 北向 Dual-Era(客户端 → 网关)

核心文件:McpInitHandlerMCPUtilsMCPPayloadGeneratorMcpMediator

  1. 协议探测(新工具类,建议 MCPProtocolNegotiator
    • Legacy 信号:method=initialize 或存在 Mcp-Session-Id
    • Modern 信号:MCP-Protocol-Version: 2026-07-28,或 body _meta.protocolVersion,或 Mcp-Method,或 server/discover
    • 结果写入 MessageContextMCP_PROTOCOL_VERSIONMCP_PROTOCOL_ERA
  2. 方法解析:优先 Mcp-Method 头,回退 JSON-RPC method;保证 throttle/auth/analytics 与 2.0 头驱动一致
  3. ALLOWED_METHODS + processInternalRequest
    • 增加 server/discover(网关自建 MCP 时返回 capabilities / serverInfo,替代 2.0 握手)
    • Legacy:保持 initialize / notifications/initialized 流程
    • Modern:允许首包直接 tools/list / tools/call / server/discover(不要求先 initialize)
  4. validateInitializeRequest / getInitializeResponse
    • 接受 1.0 与 2.0 版本字符串;回复 echo 协商版本(不再写死)
    • Modern 客户端若误发 initialize:返回明确错误或兼容降级(本方案:兼容应答并标记 era=legacy for this connection,避免硬拒)
  5. 鉴权例外isNoAuthMCPRequest
    • Legacy:维持现有 ping / notification / resources / prompts
    • Modern:将 server/discover 纳入与 initialize 同级策略(本方案:需认证,与 tools/list 一致,避免未授权探测;若产品要求公开 discover,可再改配置开关)
  6. Session
    • Legacy:initialize 成功时签发 Mcp-Session-Id 响应头;后续 POST/GET 可选携带(本方案:不强制校验粘滞,但透传/存储到 context 供南向 1.0 使用)
    • Modern:不签发、不要求 Mcp-Session-Id
  7. Streamable GET /mcp
    • Legacy:保持现有 SSE preamble(自建)/ SERVER_PROXY 透传
    • Modern:自建路径返回 405 或空闲置通道说明(本方案:对 modern 请求返回 405 Method Not Allowed,因 2.0 无 server-initiated 回推依赖);SERVER_PROXY 仍透传给后端自决
  8. 自建 MCP(DIRECT_BACKEND / EXISTING_API
    • tools/listtools/call 结果形状按北向 era 输出;2.0 列表可带 ttlMs/cacheScope 等字段(有则填,无则省略)
    • OUT 包装逻辑按 era 分支错误码映射(如 resource missing -32002-32602 仅对 modern)

Phase 2 — 南向 Dual-Era(网关 → 后端)

2A. Publisher 发现客户端

改造 MCPInitializerAndToolFetcher

  1. 构造/方法增加 protocolVersion 参数(来自校验请求或已存 metadata)
  2. 1.0 路径:保持 initialize → 读 Mcp-Session-Idnotifications/initializedtools/list + MCP-Protocol-Version
  3. 2.0 路径:发送 MCP-Protocol-Version: 2026-07-28 + Mcp-Method;用 server/discover(若后端支持)或直接 tools/list;body 带 _meta不依赖 session
  4. 校验/刷新入口(McpServersApiServiceImpl / RestApiPublisherUtils)写入探测到的实际版本到 metadata.protocolVersion

2B. SERVER_PROXY 运行时

  1. Synapse 透传保证不剥离:MCP-Protocol-VersionMcp-Session-Id(1.0)、Mcp-Method/Mcp-Name(2.0)、以及 JSON body _meta
  2. 从订阅/API 元数据读取后端 protocolVersion 注入 MessageContext(需确认 keymgt API 实体是否带 metadata;若无,在网关 DataHolder/部署产物中补充 protocolVersion 字段)
  3. 同世代:透传(现逻辑),tools/list 仍可由网关用已发布目录合成(保持现行为)
  4. 跨世代转译(新模块,建议 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 缓存模式对齐;多节点后续再上分布式)。

2C. 自建 MCP 南向

DIRECT_BACKEND / EXISTING_APItools/call→REST 与 MCP 版本无关;仅保证北向应答符合客户端 era(Phase 1)。


Phase 3 — 横切:鉴权、限流、分析、CORS

  1. ThrottleHandler:继续仅对 tools/call 限流;method 来源含 Mcp-Method
  2. Analytics:填充 MCP_PROTOCOL_VERSION / era / sessionId(legacy)到 SynapseAnalyticsDataProvider custom props
  3. APIKeyValidator:tool→resource 映射不因 era 改变
  4. WWW-Authenticate / well-known:保持;核对 2.0 对 iss 的更严校验不破坏现有 metadata 响应

Phase 4 — 测试与验收矩阵

场景 期望
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 头解析。


主要改动文件(按优先级)

  1. APIConstants.java — 版本/方法/头
  2. 新建 MCPProtocolNegotiator + MCPProtocolTranslator(gateway 包下)
  3. McpInitHandler.java / MCPUtils.java / MCPPayloadGenerator.java / McpMediator.java
  4. MCPInitializerAndToolFetcher.java + Publisher validate/create/refresh 调用链
  5. APIMappingUtil / CORS / metadata 校验
  6. Throttle + Analytics providers
  7. 对应 unit tests

不在本清单:Helm chart、Devportal UI 大改、完整 MCP Apps/Tasks 扩展(仅保证 core tools/list/call/discover/initialize)。

网关如何知道后端mcp是哪个版本

靠的是 MCP Server 上配置的 protocolVersion(表示南向后端协议),不是每次请求去猜后端。

数据从哪来

  1. 创建/更新时写入
    Publisher 在 MCP Server DTO 里带 protocolVersion

    • 2025-06-18 → 后端是 MCP 1.0
    • 2026-07-28 → 后端是 MCP 2.0
    • 不填则默认 2025-06-18
  2. 落库
    写到 AM_API_METADATA,key 为 protocolVersion

  3. 部署到网关
    打进 Gateway 部署产物的 additionalProperties,运行时挂到 keymgt API.protocolVersion / apiProperties

  4. 请求时读取
    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

运维时怎么填

  • 明确后端是 1.0 / 2.0:创建 MCP Server 时设对 protocolVersion
  • 校验第三方 MCP:先按 1.0 拉 tools,失败再试 2.0(validateThirdPartyMCPServer);成功后建议把对应版本写回该 Server 的 protocolVersion

结论: 网关“知道”后端是几,是因为你(或校验流程)把它记在 MCP Server 配置里,并随部署带到网关;运行时只读配置,不做握手探测。

posted @ 2026-08-24 10:00  张占岭  阅读(2)  评论(0)    收藏  举报