【ContextForge】核心架构与设计原理深度解析:MCP / A2A / REST / gRPC 全协议联邦网关

如果 MCP 协议是「Agent 向现实世界开枪的扳机」,那么 ContextForge (IBM/mcp-context-forge) 就是把扳机组装成一台带保险、带弹匣、可审计的工业级武器平台的开源方案。它不是简单的反向代理——它是把 MCP / A2A / REST / gRPC 四种协议统一成单一接入点,在其上叠加 40+ 插件、SSRF 防护、JWT 转发审计、UAID 跨集群联邦的真正「AI 基础设施网关」。

前言:为什么 2026 年还需要一个 MCP Gateway?

读完你会得到:

  1. 三 Gateway × 五协议 的统一接入架构 —— 看清 Tools/Agent/API 三个网关如何把 MCP/A2A/REST/gRPC/Streamable HTTP 收束成一个 endpoint
  2. cpex 插件框架 的 Hook 时序、Enforce/Permissive 双模式、PluginConfigOverride on_error 处理 —— 不是配置,是工业级执行引擎
  3. REST/gRPC-to-MCP 虚拟化 的反射协议机制 —— 把任意 legacy API 转成 MCP-compliant
  4. UAID 跨网关路由 与 Bearer Token 转发的「Fail-closed 默认」安全哲学
  5. Redis 多集群联邦 + TTL 缓存 + 失效广播 的工程化做法
  6. OpenTelemetry 全链路可观测性 的 5 大后端(Phoenix/Jaeger/Zipkin/Tempo/DataDog)
  7. 从零搭建一个生产级 MCP Gateway 的 MVP —— 哪些组件必须、哪些可以推迟

一、ContextForge 是什么?

1.1 一句话定位

ContextForge 是一个把 MCP、A2A、REST/gRPC 四种协议联邦成单一接入点的开源 AI Gateway,由 IBM 在 2026 年开源(Apache-2.0,⭐4,341,Python 100%,单仓 3,176 节点、430MB 大仓)。它在协议翻译层、插件层、可观测层、联邦层、安全层都做到了生产级深度,是当前 MCP 生态里最接近企业级 AI Gateway 的开源实现。

1.2 解决了什么具体问题?

2026 年的 AI 基础设施栈已经不再是「一个 LLM + 一个 prompt」这么简单。一个企业级 Agent 通常会:

graph LR
    A["🤖 Agent"] -->|调| M1["📦 MCP Server A (stdio)"]
    A -->|调| M2["📦 MCP Server B (sse)"]
    A -->|调| M3["📦 MCP Server C (streamable-http)"]
    A -->|调| R1["🌐 REST API"]
    A -->|调| G1["🔧 gRPC Service"]
    A -->|协作| B1["🧑 Agent X (A2A)"]
    A -->|协作| B2["🧑 Agent Y (A2A)"]
    
    style A fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style M1 fill:#E8D5F5,stroke:#CE93D8,color:#333
    style M2 fill:#E8D5F5,stroke:#CE93D8,color:#333
    style M3 fill:#E8D5F5,stroke:#CE93D8,color:#333
    style R1 fill:#FFE4B5,stroke:#FFB347,color:#333
    style G1 fill:#FFE4B5,stroke:#FFB347,color:#333
    style B1 fill:#B5EAD7,stroke:#7FC8A9,color:#333
    style B2 fill:#B5EAD7,stroke:#7FC8A9,color:#333

没有 Gateway 时的痛点立刻出现:

  • 协议碎片化:5 种协议(stdio/SSE/WebSocket/streamable-HTTP/REST)5 套 client SDK
  • 认证混乱:每个 MCP server 自己实现 OAuth;每个 REST API 自己的 token
  • 可观测缺失:谁调了哪个 tool、传了什么参数、耗时多久、是否有 prompt injection,毫无集中记录
  • 联邦空白:A 集群的 tool 调用 B 集群的 server,没有跨集群身份与审计
  • 安全失守:SSRF 攻击可以把 Agent 引导到内部 metadata endpoint;插件注入可以绕过 MCP server 自带的安全检查

ContextForge 引入后:

graph TB
    subgraph Clients["🤖 Agent 客户端层"]
        A1["Agent 1<br/>Claude/Cursor/Codex"]
        A2["Agent 2"]
        A3["Agent N"]
    end
    
    subgraph Gateway["🔀 ContextForge AI Gateway"]
        T["🛠️ Tools Gateway<br/>MCP/REST/gRPC/TOON"]
        AG["🧑 Agent Gateway<br/>A2A + OpenAI/Anthropic 兼容"]
        AP["🌐 API Gateway<br/>Rate Limit/Auth/Retry/Reverse Proxy"]
        PL["🔌 Plugin Layer<br/>cpex 40+ 插件"]
        OB["📈 Observability<br/>OpenTelemetry + 5 后端"]
    end
    
    subgraph Federation["🌍 Federation Layer"]
        R["🔴 Redis<br/>Cache + Session + Pub/Sub"]
        K8s["☸️ Multi-Cluster K8s"]
    end
    
    subgraph Backend["📦 后端服务"]
        M1["MCP Server A"]
        M2["MCP Server B"]
        M3["MCP Server C"]
        R1["REST API"]
        G1["gRPC Service"]
        AA1["A2A Agent X"]
        AA2["A2A Agent Y"]
    end
    
    A1 -->|统一 endpoint| T
    A1 -->|统一 endpoint| AG
    A1 -->|统一 endpoint| AP
    T --> PL
    AG --> PL
    AP --> PL
    PL --> OB
    T <--> R
    AG <--> R
    AP <--> R
    K8s -.->|UAID 跨集群| R
    T --> M1
    T --> M2
    T --> M3
    AP --> R1
    AP --> G1
    AG --> AA1
    AG --> AA2
    
    style T fill:#FFD1DC,stroke:#FF8FA3,color:#333
    style AG fill:#B5EAD7,stroke:#7FC8A9,color:#333
    style AP fill:#FFE4B5,stroke:#FFB347,color:#333
    style PL fill:#E8D5F5,stroke:#CE93D8,color:#333
    style OB fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style R fill:#FFC0CB,stroke:#FF69B4,color:#333
    style K8s fill:#C7CEEA,stroke:#9FA8DA,color:#333

1.3 仓库统计与定位

字段
仓库IBM/mcp-context-forge(Apache-2.0)
仓库大小430 MB(含 Helm charts、文档、55+ Alembic 迁移、3,176 节点)
⭐ Stars4,341(2026-08-20)
主语言Python 100%
提交活跃度2026-08-19 最新推送
版本1.0.0-RC-3(PyPI 上以 mcp-contextforge-gateway 发布)
测试规模7,000+ tests + 完整 lint + pre-commit + doctest 覆盖率报告
部署形态PyPI / Docker / Podman / Helm / Makefile compose 栈 / airgapped
文档1086 行 README + 完整 MkDocs 站点 + 60+ ADR(架构决策记录)
关键贡献者Mihai Criveti(IBM,CMO of ContextForge)
LicenseApache-2.0

二、整体架构

ContextForge 的核心是三层 Gateway × 五种协议的矩阵。入口统一为一个 endpoint,但内部根据请求类型分流到不同的处理引擎。

2.1 顶层架构图

flowchart TB
    Client["🤖 Agent 客户端<br/>Claude Code / Cursor / Codex / 自研"]
    
    subgraph Edge["🌐 Edge Layer"]
        Nginx["Nginx 反向代理<br/>(缓存 + TLS + 限流)"]
        AuthMW["🔐 认证中间件<br/>JWT + Basic + SSO"]
        CSP["🛡️ CSP / CORS / SSRF 防护"]
    end
    
    subgraph Core["⚙️ Core Gateway (FastAPI :4444)"]
        direction TB
        Main["mcpgateway/main.py<br/>572KB 单一入口"]
        
        subgraph Routers["📡 Routers Layer"]
            ToolsR["tools router<br/>tools/list / /invoke"]
            ServersR["servers router<br/>联邦 MCP server 注册"]
            ResourcesR["resources router<br/>URI 路由 + MIME"]
            GatewaysR["gateways router<br/>联邦网关"]
            A2AR["a2a router<br/>A2A 协议"]
        end
        
        subgraph Services["🧩 Services Layer (50+ service)"]
            ToolSvc["ToolService"]
            GatewaySvc["GatewayService<br/>联邦同步"]
            A2ASvc["A2AService"]
            LLMSvc["LLMProxyService"]
            GrpcSvc["gRPCService"]
            AuditSvc["AuditTrailService"]
        end
        
        subgraph Plugin["🔌 Plugin Layer (cpex)"]
            PluginMgr["TenantPluginManagerFactory<br/>TTL 30s + Redis overrides"]
            Hooks["13 个 Hook 时机<br/>prompt_pre_fetch / tool_pre_invoke / ..."]
            Plugins40["40+ 插件<br/>(PII Guardian / CircuitBreaker / CitationValidator)"]
        end
        
        subgraph Transports["📨 Transports Layer"]
            SSE["SSE (914 lines)"]
            WS["WebSocket"]
            Stdio["stdio"]
            StreamH["streamable-http (270KB)"]
            REST["REST reverse proxy"]
            gRPC["gRPC reflection"]
        end
    end
    
    subgraph Data["💾 Data Layer"]
        PG["🗄️ PostgreSQL<br/>55+ 表"]
        Redis["🔴 Redis<br/>Cache + Session + Plugin overrides"]
        Vault["🔐 Vault<br/>token 加密存储"]
    end
    
    subgraph Obs["📈 Observability"]
        OTel["OpenTelemetry<br/>OTLP 协议"]
        Backend["Phoenix / Jaeger / Zipkin<br/>Tempo / DataDog / New Relic"]
    end
    
    subgraph Backends["📦 后端 Backend"]
        MCPBack["MCP Servers"]
        RESTBack["REST APIs"]
        GRPCBack["gRPC Services"]
        A2ABack["A2A Agents"]
    end
    
    Client --> Nginx
    Nginx --> AuthMW
    AuthMW --> CSP
    CSP --> Main
    Main --> Routers
    Routers --> Services
    Services --> Plugin
    Services --> Transports
    Plugin --> Transports
    Transports --> Backends
    Services <--> PG
    Services <--> Redis
    Services <--> Vault
    Plugin <--> Redis
    Services --> OTel
    OTel --> Backend
    
    style Main fill:#FFD1DC,stroke:#FF8FA3,color:#333
    style Plugin fill:#E8D5F5,stroke:#CE93D8,color:#333
    style Redis fill:#FFC0CB,stroke:#FF69B4,color:#333
    style OTel fill:#C7CEEA,stroke:#9FA8DA,color:#333

2.2 后端服务拆分

mcpgateway/services/ 下有 50+ 个服务,按职责切分为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mcpgateway/services/
├── gateway_service.py # 7492 行 - 联邦网关核心
├── tool_service.py # 工具生命周期管理
├── a2a_service.py # A2A Agent 注册与路由
├── a2a_server_service.py # A2A server-side 实现
├── a2a_protocol.py # 跨版本 A2A 请求准备
├── llm_provider_service.py # LLM provider 抽象
├── llm_proxy_service.py # LLM 请求代理 + 缓存
├── grpc_service.py # gRPC reflection 服务发现
├── audit_trail_service.py # 审计轨迹
├── encryption_service.py # OAuth token 加密存储
├── oauth_resource.py # OAuth resource server
├── token_scoping.py # token scope 隔离
├── dcr_service.py # Dynamic Client Registration
├── elicitation_service.py # MCP Elicitation 处理
├── leader_election.py # Redis-based 选主
├── event_service.py # 事件总线
├── log_aggregator.py # 日志聚合
├── csrf_service.py # CSRF token 防护
├── content_security.py # 内容安全策略
└── ... (50+ services)

核心 main.py 自身就 572KB / ~17,000 行——是单一入口、单一应用(FastAPI app)的「单体架构」。这种设计的工程取舍我们稍后在优缺点分析里展开。

2.3 docker-compose 栈

生产部署通过 make compose-up 启动的完整栈:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# docker-compose.yml 核心服务(精简版)
services:
gateway:
image: ghcr.io/ibm/mcp-context-forge:latest
replicas: 3 # 3 副本水平扩展
environment:
- DATABASE_URL=postgresql+psycopg://postgres:****@postgres:5432/mcp
- REDIS_URL=redis://redis:6379/0
- JWT_SECRET_KEY=${JWT_SECRET_KEY}
- AUTH_ENCRYPTION_SECRET=${AUTH_ENCRYPTION_SECRET}
depends_on: [postgres, redis]

postgres:
image: postgres:16
volumes: [pgdata:/var/lib/postgresql/data]

redis:
image: redis:7-alpine
command: redis-server --maxmemory 1gb --maxmemory-policy allkeys-lru

nginx:
image: nginx:alpine
ports: ["8080:8080"]
# 反向代理 + TLS 终止 + 静态资源缓存

三、协议联邦层(Tools/Agent/API Gateway)

3.1 三 Gateway 抽象矩阵

ContextForge 把所有请求收束到 3 个 Gateway,每个 Gateway 都有独立的 router、独立的 service、独立的 schema,但都共享同一套 plugin pipeline 和 observability hook。

Gateway路由前缀协议联邦范围典型场景
Tools Gateway/tools, /servers, /resources, /promptsMCP / REST / gRPC-to-MCP跨集群 MCP server 联邦Agent 调用任意后端能力
Agent Gateway/a2a, /agents, /rpcA2A 协议 + OpenAI/Anthropic 兼容外部 AI Agent 注册Agent ↔ Agent 跨厂商协作
API Gateway/api, /restREST reverse proxyREST API 联邦把 legacy REST 转成 MCP tool

3.2 gRPC-to-MCP 反射协议翻译

ContextForge 最具差异化的能力之一是 gRPC → MCP 翻译:通过 gRPC server reflection 协议自动发现 service 和 method,再把每个 method 包成 MCP tool。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# mcpgateway/services/grpc_service.py 核心:reflection-based service discovery
# 来自 mcpgateway/services/grpc_service.py:1-80

async def discover_grpc_services(endpoint: str) -> list[dict]:
"""通过 gRPC server reflection 自动发现 service 列表。

Returns:
[{"name": "helloworld.Greeter", "methods": ["SayHello", ...]}, ...]
"""
channel = grpc.aio.insecure_channel(endpoint)
stub = ServerReflectionStub(channel)
services = await stub.ListServices()

discovered = []
for service in services:
# 用 reflection 拿到 service descriptor
descriptor = await stub.GetServiceDescriptor(service.name)
for method in descriptor.methods:
discovered.append({
"service": service.name,
"method": method.name,
"input_type": method.input_type,
"output_type": method.output_type,
})
return discovered

关键设计:不是手工写 schema,是用 reflection 自动生成 JSON Schema,存到 Postgres 的 grpc_services 表,再注册为 virtual MCP tool。整个流程 Agent 不需要知道「这个后端是 gRPC」,它只看到一个普通 MCP tool。

3.3 REST-to-MCP 虚拟化

类似地,REST API 也可以自动包装成 MCP tool。核心是把 OpenAPI/Swagger spec 转成 JSON Schema,再注册。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# mcpgateway/services/tool_service.py - REST-to-MCP 包装
# 来自 mcpgateway/services/tool_service.py(节选)

async def ingest_rest_api(spec: dict, base_url: str) -> list[Tool]:
"""从 OpenAPI spec 自动生成 MCP tool 列表。

Args:
spec: OpenAPI/Swagger 3.x 文档
base_url: REST API 的 base URL

Returns:
每个 OpenAPI operation 对应一个 MCP Tool
"""
tools = []
for path, methods in spec['paths'].items():
for method, op in methods.items():
if method.upper() not in {'GET','POST','PUT','DELETE','PATCH'}:
continue
tool = Tool(
name=f"{op.get('operationId', f'{method}_{path}')}",
description=op.get('summary', op.get('description', '')),
input_schema=_openapi_to_jsonschema(op.get('parameters', []) +
[op.get('requestBody', {})]),
endpoint=f"{base_url}{path}",
method=method.upper(),
headers=_extract_headers(op),
auth=_extract_security(op),
)
tools.append(tool)
return tools

值得注意的工程取舍

  • jsonpath_ng 库处理复杂 JSONPath 表达式(用于插件链路里的 payload transform)
  • orjson 替代标准 json2-3x faster 序列化/反序列化)
  • psycopg3 优化(带 prepared statement cache)

3.4 协议联邦的数据流

sequenceDiagram
    participant Agent as 🤖 Agent
    participant GW as ContextForge Gateway
    participant Plugin as 🔌 Plugin Layer
    participant Tr as 📨 Transport
    participant Backend as 📦 Backend
    
    Agent->>GW: POST /tools/invoke {"name":"greeter.SayHello","args":{...}}
    GW->>GW: AuthMiddleware (JWT 验证)
    GW->>GW: CSPMiddleware (SSRF 防护)
    GW->>Plugin: ToolPreInvokeHook(payload)
    Plugin-->>GW: PluginViolation? return :abort
    GW->>Tr: 路由到对应 transport
    Note over Tr: gRPC-to-MCP reflection<br/>REST-to-MCP adapter<br/>原生 MCP (stdio/SSE/...)
    Tr->>Backend: 实际调用
    Backend-->>Tr: 响应
    Tr-->>GW: 响应 (JSON-RPC 2.0 格式)
    GW->>Plugin: ToolPostInvokeHook(payload, result)
    Plugin-->>GW: transform / augment / redact
    GW-->>Agent: {"result": ..., "trace_id": "..."}
    GW->>Plugin: AuditHook (span emit)
    Plugin->>OTel: trace.span().end()

四、cpex 插件框架

cpex (ContextForge Plugin EXtension) 是 ContextForge 自研的插件框架,是把 MCP/A2A/REST 协议层与业务策略层解耦的关键设计。

4.1 Hook 时序与生命周期

cpex 在 13 个时间点暴露 hook,覆盖工具调用、资源获取、提示获取的完整生命周期:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
REQUEST FLOW (Prompt side):
prompt_pre_fetch → 调取 prompt template 前
prompt_post_fetch → 调取 prompt template 后
prompt_pre_render → 渲染 Jinja2 前
prompt_post_render → 渲染后

REQUEST FLOW (Resource side):
resource_pre_fetch → 拉取 URI resource 前
resource_post_fetch → 拉取 URI resource 后

REQUEST FLOW (Tool side):
tool_pre_invoke → 调工具前
tool_post_invoke → 调工具后
tool_pre_invoke_in_batch → 批量调前
tool_post_invoke_in_batch → 批量调后

RESPONSE FLOW (HTTP auth):
http_auth_check_pre → HTTP 认证前
http_auth_check_post → HTTP 认证后

OBSERVABILITY:
control_payload → span 字段自定义

每个 Hook 是一个签名稳定的回调,参数是 cpex 的 Payload / Result 数据类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# cpex 插件签名(来自 plugins/circuit_breaker/circuit_breaker.py)
# 来自 plugins/circuit_breaker/circuit_breaker.py:1-80

from cpex.framework import (
Plugin,
PluginConfig,
PluginContext,
PluginViolation,
ToolPostInvokePayload,
ToolPostInvokeResult,
ToolPreInvokePayload,
ToolPreInvokeResult,
)


class CircuitBreakerPlugin(Plugin):
"""每工具独立熔断器:错误率超阈值或连续失败 N 次则断开。"""

async def tool_pre_invoke(
self, payload: ToolPreInvokePayload, context: PluginContext
) -> ToolPreInvokeResult:
state = _get_state(payload.tool_name)
# ... 三态状态机:CLOSED → OPEN → HALF_OPEN ...
if state.open_until > _now():
return ToolPreInvokeResult(
continue_=False,
violation=PluginViolation(
code="CIRCUIT_OPEN",
message="Circuit breaker is open; try again later",
hook="tool_pre_invoke",
),
)
return ToolPreInvokeResult(continue_=True)

4.2 插件 Manifest 与发现

每个插件用一个 plugin-manifest.yaml 描述自己的能力:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# plugins/circuit_breaker/plugin-manifest.yaml
description: "Trips per-tool breaker on high error rates or consecutive failures; blocks during cooldown."
author: "ContextForge"
version: "0.1.0"
tags: ["reliability", "stability", "sre"]
available_hooks:
- "tool_pre_invoke"
- "tool_post_invoke"
default_config:
error_rate_threshold: 0.5
window_seconds: 60
min_calls: 10
consecutive_failure_threshold: 5
cooldown_seconds: 60
tool_overrides: {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# plugins/citation_validator/plugin-manifest.yaml
description: "Validates citations/links by checking reachability and optional content keywords."
author: "ContextForge"
version: "0.1.0"
tags: ["validation", "links", "citation"]
available_hooks:
- "resource_post_fetch"
- "tool_post_invoke"
default_config:
fetch_timeout: 6.0
require_200: true
content_keywords: []
max_links: 20
block_on_all_fail: false
block_on_any_fail: false
user_agent: "MCP-Context-Forge/1.0 CitationValidator"

plugins/config.yaml 是全局插件注册中心:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# plugins/config.yaml 片段
plugins:
- name: "SpanAttributeCustomizer"
kind: "plugins.span_attribute_customizer.span_attribute_customizer.SpanAttributeCustomizerPlugin"
description: "Customizes OpenTelemetry span attributes for enhanced observability and compliance"
version: "1.0.0"
author: "ContextForge Team"
hooks: ["tool_pre_invoke", "resource_pre_fetch", "resource_post_fetch"]
tags: ["observability", "telemetry", "opentelemetry", "spans", "attributes"]
mode: "disabled" # 可选 permissive / enforce
priority: 10 # 数字越小越先执行
conditions: []
config:
attribute_mapping:
"plugin.name": "controls.artifact.name"
"plugin.uuid": "controls.artifact.id"
"plugin.mode": "controls.enforcement.mode"
"plugin.priority": "controls.execution.priority"
"plugin.timeout": "controls.execution.timeout"

- name: "ArgumentNormalizer"
kind: "plugins.argument_normalizer.argument_normalizer.ArgumentNormalizerPlugin"
description: "Normalizes Unicode, whitespace, casing, dates, and numbers in args"
hooks: ["prompt_pre_fetch", "tool_pre_invoke"]
tags: ["normalize", "inputs", "whitespace", "unicode", "dates", "numbers"]
mode: "disabled"
priority: 40

4.3 Enforce / Permissive / Disabled 三态模式

每个插件有 3 种执行模式:

模式行为适用场景
permissive观察 + transform,违规不阻断数据脱敏、参数规范化、日志记录
enforce阻断模式,违规抛 PluginViolationPII 防护、SSRF 防御、citation 校验
disabled不加载该插件默认状态,按需启用

4.4 TenantPluginManagerFactory 的 TTL 缓存

mcpgateway/plugins/gateway_plugin_manager.py 提供租户隔离的插件管理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# mcpgateway/plugins/gateway_plugin_manager.py:30-100
# 来自 mcpgateway/plugins/gateway_plugin_manager.py:30-100

class TenantPluginManagerFactory:
"""Standalone factory for context-scoped TenantPluginManager instances.

TTL caching, Redis mode overrides, invalidate_all/invalidate_team,
on_error support, and optional DB wiring for per-tool plugin bindings.
"""

DEFAULT_CACHE_TTL = 30 # 30 秒 TTL 缓存
CONTEXT_ID_SEPARATOR = "::" # 格式: "<team_id>::<tool_name>"

def __init__(
self,
yaml_path: str,
timeout: int = 30,
observability: Optional[ObservabilityProvider] = None,
hook_policies: Optional[dict[str, HookPayloadPolicy]] = None,
cache_ttl: Optional[int] = None,
db_factory: Optional[Callable[[], Session]] = None,
):
self._base_config: Config = enrich_config_plugin_metadata(ConfigLoader.load_config(yaml_path))
self._timeout = timeout
# ...
self._managers: dict[str, _CachedManager] = {}
self._inflight: dict[str, asyncio.Task[TenantPluginManager]] = {}
self._lock = asyncio.Lock()
self._cache_ttl = cache_ttl if cache_ttl is not None else self.DEFAULT_CACHE_TTL

async def get_manager(self, context_id: str) -> TenantPluginManager:
"""获取(或构建并缓存)一个 TenantPluginManager。"""
# 双检查锁:先看缓存、再看 in-flight、最后才构建
if context_id in self._managers:
cached = self._managers[context_id]
if not cached.is_expired(self._cache_ttl):
return cached.manager
if context_id in self._inflight:
return await self._inflight[context_id]
# ... 构建新 manager ...

关键设计

  • context_id = "<team_id>::<tool_name>" —— 不同团队不同工具的插件配置独立
  • _CachedManager 记录构建时间戳,cache_ttl 默认 30 秒(30s 后必须重读 YAML)
  • _inflight dict 用 asyncio.Task重复构建(同一 context_id 多 worker 同时请求时只构建一次)
  • invalidate_all / invalidate_team 用于跨 worker 失效广播

4.5 插件执行流水线

sequenceDiagram
    participant Req as 📥 Tool Request
    participant Mgr as TenantPluginManagerFactory
    participant MgrInst as TenantPluginManager (per-tool)
    participant Pre as pre_invoke plugins
    participant Backend as 📦 Backend
    participant Post as post_invoke plugins
    
    Req->>Mgr: get_manager("team1::toolA")
    Mgr->>MgrInst: cached? or build+cache (TTL 30s)
    Mgr-->>Req: manager instance
    
    req->>MgrInst: invoke_tool_pre(payload)
    loop for each pre plugin in priority order
        MgrInst->>Pre: hook(payload, ctx)
        alt violation
            Pre-->>MgrInst: PluginViolation
            MgrInst-->>Req: abort + audit
        else transform
            Pre-->>MgrInst: mutated payload
        end
    end
    
    MgrInst->>Backend: actual tool call
    Backend-->>MgrInst: result
    
    MgrInst->>Post: invoke_tool_post(payload, result)
    loop for each post plugin
        MgrInst->>Post: hook(payload, result, ctx)
        Post-->>MgrInst: transform / redact / augment
    end
    
    MgrInst-->>Req: final result + spans

五、Tool Service 与联邦同步

mcpgateway/services/gateway_service.py(7,492 行)是联邦同步的核心。它把多个 gateway 实例的 tool/resource/prompt 状态做周期性同步,并维护活跃网关集合。

5.1 联邦同步流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# mcpgateway/services/gateway_service.py 核心同步逻辑
# 来自 mcpgateway/services/gateway_service.py:1-80(精简)

class GatewayService(BaseService):
"""Gateway Service Implementation.

Implements gateway federation according to the MCP specification.
- Gateway discovery and registration
- Capability aggregation
- Health monitoring
- Active/inactive gateway management
"""

def __init__(self):
self._active_gateways: set = set()
self._http_client: httpx.AsyncClient = httpx.AsyncClient(
timeout=httpx.Timeout(30.0, connect=5.0)
)
# ...

async def register_gateway(self, gateway_url: str, capabilities: dict) -> None:
"""把一个新 gateway 加入联邦,验证 + 加入活跃集合。"""
async with self._lock:
# 1. 健康检查
health = await self._http_client.get(f"{gateway_url}/health")
if health.status_code != 200:
raise GatewayUnreachable(gateway_url)
# 2. capability 拉取
caps = await self._http_client.get(f"{gateway_url}/capabilities")
# 3. 加入活跃集合
self._active_gateways.add(gateway_url)
# 4. 持久化到 DB
await self._persist_gateway(gateway_url, caps)

5.2 A2A 服务注册

A2A (Agent-to-Agent) 协议让外部 AI Agent(OpenAI/Anthropic/自研)注册到 ContextForge,统一被发现和路由。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# mcpgateway/services/a2a_service.py - A2A Agent 注册
# 来自 mcpgateway/services/a2a_service.py(节选)

async def register_a2a_agent(
name: str,
endpoint: str,
protocol_version: str = "1.0",
auth: Optional[dict] = None,
) -> A2AAgent:
"""注册一个外部 A2A Agent。

Args:
name: Agent 名称
endpoint: Agent 的 RPC endpoint
protocol_version: A2A 协议版本
auth: OAuth/token 信息(加密存储)
"""
# 1. 探活
async with httpx.AsyncClient() as client:
resp = await client.get(f"{endpoint}/.well-known/a2a.json")
if resp.status_code != 200:
raise A2ARegistrationError(f"Agent not reachable: {endpoint}")
manifest = resp.json()

# 2. 加密存储凭据
encrypted_auth = encrypt_oauth_config(auth) if auth else None

# 3. 持久化
agent = A2AAgent(
name=name,
endpoint=endpoint,
protocol_version=protocol_version,
manifest=manifest,
auth=encrypted_auth,
capabilities=manifest.get('capabilities', []),
)
db.add(agent)
db.commit()

return agent

5.3 gRPC Service:反射协议翻译

mcpgateway/services/grpc_service.py 实现 gRPC reflection-based 服务发现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# mcpgateway/services/grpc_service.py 节选(精简版)
# 来自 mcpgateway/services/grpc_service.py(节选)

async def register_grpc_service(
name: str,
endpoint: str,
reflection_endpoint: str,
) -> list[Tool]:
"""注册一个 gRPC service 为 MCP tool 集合。

Args:
name: 服务名称
endpoint: gRPC endpoint (host:port)
reflection_endpoint: gRPC reflection 服务地址
"""
channel = grpc.aio.insecure_channel(reflection_endpoint)
stub = ServerReflectionStub(channel)

# 1. ListServices via reflection
services = await stub.ListServices()

tools = []
for svc in services:
# 2. GetServiceDescriptor via reflection
desc = await stub.GetServiceDescriptor(svc.name)
for method in desc.methods:
tool = Tool(
name=f"{desc.name}.{method.name}",
description=method.documentation or f"{svc.name}.{method.name}",
input_schema=protobuf_to_jsonschema(method.input_type),
output_schema=protobuf_to_jsonschema(method.output_type),
endpoint=endpoint,
method=method.name,
transport="grpc",
)
tools.append(tool)

# 3. 持久化 + 注册为 virtual MCP server
grpc_svc = GrpcService(
name=name,
endpoint=endpoint,
tools=tools,
)
db.add(grpc_svc)
db.commit()
return tools

六、可观测性:OpenTelemetry 全链路

6.1 OTLP 多后端支持

ContextForge 内置 OpenTelemetry 集成,默认零开销(禁用时直接走 no-op),启用后支持 5 大 OTLP 后端:

后端用途关键能力
PhoenixLLM 专用追踪token 用量、prompt 内容、cost
Jaeger通用分布式追踪服务依赖图、慢请求分析
Zipkin通用追踪(轻量)单服务延迟
TempoGrafana Stack 追踪与 Grafana 看板集成
DataDog / New RelicSaaS APM全栈监控、告警

6.2 Span Attribute Customizer 插件

通过插件机制,可以自定义 span 字段,满足合规要求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# plugins/config.yaml - SpanAttributeCustomizer 插件
- name: "SpanAttributeCustomizer"
mode: "permissive" # 仅修改 span,不阻断
priority: 10 # 最早执行,确保后续插件看到正确字段
config:
attribute_mapping:
"plugin.name": "controls.artifact.name" # 字段重命名
"plugin.uuid": "controls.artifact.id"
"plugin.mode": "controls.enforcement.mode"
"plugin.priority": "controls.execution.priority"
"plugin.timeout": "controls.execution.timeout"
allowed_baggage_span_attributes:
- "tenant.id"
- "user.id"
emit_baggage_prefixed_attributes: false

工程价值:在不修改 OTel SDK 的前提下,把 OpenTelemetry 标准属性映射到企业内部的命名约定(如 NIST、FedRAMP 合规字段名)。

6.3 trace_context 与 trace_redaction

mcpgateway/utils/trace_context.pytrace_redaction.py 提供:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# mcpgateway/utils/trace_context.py 节选
# 来自 mcpgateway/utils/trace_context.py(精简版)

from opentelemetry import trace
from opentelemetry.trace import Status, StatusCode

def set_trace_session_id(session_id: str) -> None:
"""把 MCP session ID 注入到当前 span,方便跨服务追踪。"""
span = trace.get_current_span()
span.set_attribute("mcp.session_id", session_id)


def create_span(name: str, **attrs) -> trace.Span:
"""创建带通用属性的 span:tool/server/team/user。"""
return trace.get_tracer("mcpgateway").start_as_current_span(
name,
attributes={
"mcpgateway.component": name,
"tenant.id": get_current_tenant_id(),
"user.id": get_current_user_id(),
**attrs,
},
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# mcpgateway/utils/trace_redaction.py 节选
# 来自 mcpgateway/utils/trace_redaction.py(精简版)

SENSITIVE_KEYS = {"password", "token", "api_key", "secret", "authorization"}

def redact_payload(payload: dict) -> dict:
"""递归脱敏 payload 中的敏感字段。"""
redacted = {}
for k, v in payload.items():
if k.lower() in SENSITIVE_KEYS:
redacted[k] = "***REDACTED***"
elif isinstance(v, dict):
redacted[k] = redact_payload(v)
elif isinstance(v, list):
redacted[k] = [redact_payload(item) if isinstance(item, dict) else item
for item in v]
else:
redacted[k] = v
return redacted

关键设计:trace 数据先经过 trace_redaction 才发给 OTLP 后端,避免把 OAuth token / API key 泄到 Jaeger 里——这是企业级 OTel 集成的常见盲区。

七、安全:UAID 跨网关路由与 JWT 转发

7.1 UAID (Universal Agent ID) 跨集群路由

ContextForge 的杀手锏是 UAID (Universal Agent ID) 跨集群路由:让 A 集群的 Agent 能调用 B 集群的 tool,全程带原始用户身份

flowchart LR
    A["🤖 Agent<br/>(Cluster A)"]
    GW_A["ContextForge GW-A<br/>(JWT-Issuer A)"]
    GW_B["ContextForge GW-B<br/>(JWT-Issuer B)"]
    Tool["📦 Tool X<br/>(Cluster B)"]
    
    A -->|"Bearer Token<br/>(user@example.com)"| GW_A
    GW_A -->|"Authorization: Bearer <original token><br/>X-Forwarded-For: user@example.com"| GW_B
    GW_B -->|"verify JWT + UAID_ALLOWED_DOMAINS check"| Tool
    Tool -->|"response"| GW_B
    GW_B -->|"audit trail"| GW_A
    GW_A -->|"response"| A
    
    style GW_A fill:#C7CEEA,stroke:#9FA8DA
    style GW_B fill:#C7CEEA,stroke:#9FA8DA
    style Tool fill:#FFE4B5,stroke:#FFB347

7.2 Fail-closed 默认安全哲学

UAID 跨集群路由有 4 道安全防线:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
防线 1: UAID_ALLOWED_DOMAINS 配置
- 必须在 .env 里显式配置 trusted domains
- 空 allowlist = 阻断所有跨集群路由
- 启动时 + 运行时双重校验

防线 2: JWT Issuer Trust
- GW-A 和 GW-B 必须信任同一个 JWT issuer
- 选项 A: 共享 JWT_SECRET_KEY (单租户)
- 选项 B: 联邦 SSO (Google / GitHub / Entra ID)

防线 3: AUTH_REQUIRED + UAID_FORWARD_AUTH
- AUTH_REQUIRED=true 强制认证
- UAID_FORWARD_AUTH=true 显式允许 token 转发

防线 4: Audit Trail
- 每次跨集群调用记录 source gateway + 原始 user
- 出现异常可回溯完整链路

7.3 凭据加密存储

OAuth token、API key、SSL 私钥全部用 Fernet 加密后存入 Postgres:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# mcpgateway/services/encryption_service.py 节选
# 来自 mcpgateway/services/encryption_service.py

from cryptography.fernet import Fernet

def get_encryption_service() -> "EncryptionService":
"""单例 EncryptionService,加载 AUTH_ENCRYPTION_SECRET。"""
return _encryption_service_singleton


def protect_oauth_config_for_storage(config: dict) -> dict:
"""加密 OAuth 配置再入库。"""
enc = get_encryption_service()
protected = {}
for k, v in config.items():
if k in {"client_secret", "refresh_token", "access_token", "api_key"}:
protected[k] = enc.encrypt(v.encode()).decode()
else:
protected[k] = v
return protected

八、Redis 联邦与缓存

8.1 hiredis 83x 性能优化

mcpgateway/utils/redis_client.pyhiredis C 解析器

1
2
3
4
5
6
7
8
9
# mcpgateway/utils/redis_client.py 注释
# 来自 mcpgateway/utils/redis_client.py:1-30

"""Centralized Redis client factory for consistent configuration.

Performance: Uses hiredis C parser by default (ADR-026) for up to 83x faster
response parsing on large responses. Falls back to pure-Python parser if
hiredis is unavailable or explicitly disabled via REDIS_PARSER setting.
"""

83x 提升主要来自 redis-pydecode_responses=True + hiredis 组合,在 1000+ key 的 pub/sub 场景特别明显。

8.2 多后端缓存策略

flowchart LR
    Req["Request"] --> L1["L1: Process-local LRU<br/>(in-memory, 1ms)"]
    L1 -->|miss| L2["L2: Redis<br/>(cluster mode, 5ms)"]
    L2 -->|miss| L3["L3: DB query<br/>PostgreSQL (10ms)"]
    L3 -->|fill| L2
    L2 -->|fill| L1
    L1 --> Resp["Response"]
    
    style L1 fill:#B5EAD7,stroke:#7FC8A9
    style L2 fill:#FFC0CB,stroke:#FF69B4
    style L3 fill:#FFE4B5,stroke:#FFB347

缓存层级职责

  • L1: 单次请求内的中间结果(如 plugin transform chain 中间值)
  • L2: 跨 worker 共享的 SessionRegistry、PluginConfigOverride、ResourceCache
  • L3: Postgres 持久化(55+ 张表的 source of truth)

8.3 失效广播

跨 worker 失效用 Redis pub/sub:

1
2
3
4
5
6
7
8
9
10
11
12
# mcpgateway/plugins/gateway_plugin_manager.py - invalidate_all
async def invalidate_all(self) -> None:
"""清空所有缓存,并通过 Redis pub/sub 广播给其他 worker。"""
async with self._lock:
self._managers.clear()
# 广播给同集群其他 worker
redis = await get_redis_client()
if redis:
await redis.publish("mcpgateway:plugin:invalidate", json.dumps({
"type": "invalidate_all",
"origin": os.getpid(),
}))

九、与同类项目对比

9.1 与 microsoft/mcp-gateway 对比

两者的名字都叫 “mcp-gateway” 但定位完全不同

维度IBM/mcp-context-forgemicrosoft/mcp-gateway
定位联邦网关 + 协议翻译 + 插件生态MCP 反向代理 + Session 安全
语言Python 100%C# ASP.NET Core 8
协议覆盖MCP + A2A + REST + gRPC仅 MCP
插件系统40+ 插件,cpex 框架
联邦UAID 跨集群 + Redis
可观测OpenTelemetry + 5 后端Application Insights
协议翻译gRPC reflection + REST adapter
依赖FastAPI + SQLAlchemy + RedisK8s + Azure AD
生态40+ 开源插件,IBM 治理Microsoft 闭源生态

关键差异:microsoft/mcp-gateway 解决的是 「Agent 滥用 MCP 工具的安全防护」问题(Session 绑定、Symlink 防御、Bash denylist),而 ContextForge 解决的是 「企业级 AI 基础设施统一接入」 问题(多协议、插件、联邦、可观测)。两者可以叠加部署——ContextForge 在外、microsoft/mcp-gateway 在内。

9.2 与 LiteLLM 对比

LiteLLM 解决 **「Python 层 LLM 路由」**问题,ContextForge 解决 **「协议联邦 + AI 基础设施」**问题:

维度LiteLLMContextForge
核心抽象LLM Provider(OpenAI/Anthropic/…)Protocol Gateway(MCP/A2A/REST/gRPC)
解决域模型调用统一后端能力统一
协议支持仅 LLM HTTP APIMCP/A2A/REST/gRPC 全协议
联邦UAID + Redis 跨集群
插件callback 函数40+ cpex 插件
可观测自带 callbacksOpenTelemetry + 5 后端
运行时Python 进程内独立网关服务(worker 水平扩展)

9.3 与 Portkey-AI/gateway 对比

Portkey 是 AI Gateway 但偏 LLM 路由:

维度PortkeyContextForge
核心抽象LLM Provider + GuardrailProtocol Gateway + Plugin
Guardrail50+ 输出层规则13 Hook + Plugin 输出/输入
部署SaaS 为主 + 自托管Apache-2.0 自托管优先
生态闭源商业40+ 开源插件

ContextForge 的 输入侧 Plugin 比 Portkey 的输出侧 Guardrail 更有前置防御能力。

9.4 与 open-connector / openai-agents / LangChain 对比

  • open-connector (已写) = SaaS OAuth 连接器,类似 Composio 赛道
  • openai-agents = Agent 框架,不解决协议联邦问题
  • LangChain = LLM 链式调用框架,与 Gateway 完全正交

十、优缺点分析

10.1 架构维度对比

维度ContextForge评级
协议覆盖广度MCP/A2A/REST/gRPC 全覆盖⭐⭐⭐⭐⭐
插件可扩展性40+ 插件,cpex 框架⭐⭐⭐⭐⭐
联邦深度UAID 跨集群 + Redis + K8s⭐⭐⭐⭐⭐
可观测性OpenTelemetry + 5 后端 + 自定义 span⭐⭐⭐⭐⭐
安全纵深UAID allowlist + JWT 转发 + Fernet 加密 + SSRF 防护⭐⭐⭐⭐⭐
配置复杂度300+ 环境变量⭐⭐
学习曲线需懂 FastAPI + SQLAlchemy + OTel + cpex + 多协议⭐⭐
部署运维Postgres + Redis + K8s + Nginx + Helm,门槛高⭐⭐

10.2 左侧:架构简洁性 / 扩展性 / 易用性

架构简洁性:⭐⭐

  • 单进程 FastAPI,单一 main.py 572KB / 17,000 行——是**有意的「单体架构」**哲学(避免分布式状态)
  • 所有 service 共享同一 Postgres + Redis,部署/调试简单
  • 首次启动需要 6+ 步骤:生成 secret、下载 .env.example、init_secrets、patch-env、generate token、smoke test

扩展性:⭐⭐⭐⭐⭐

  • 40+ 插件开箱即用,覆盖 PII Guardian / Citation Validator / Circuit Breaker / PII Filter / Content Moderation / Argument Normalizer / Span Attribute Customizer / PII Guardian 等
  • 新增插件只需写一个 Python 文件 + manifest.yaml,无需改 gateway 代码
  • 水平扩展:3+ gateway replicas + Nginx LB + Redis 集群
  • 垂直扩展:worker process 数可配(GUNICORN_WORKERS

易用性:⭐⭐⭐

  • 文档齐全(1086 行 README + MkDocs 全站 + 60+ ADR),但内容量大、新人上手曲线陡
  • Admin UI 提供 web 端管理(HTMX + Alpine.js)
  • Swagger UI / ReDoc 自动生成
  • 但 300+ 环境变量需要细读 .env.example

10.3 右侧:性能 / 复杂度 / 维护性

性能:⭐⭐⭐⭐

  • hiredis C 解析器(83x faster JSON 解析)
  • orjson 替代标准 json(2-3x faster)
  • psycopg3 + prepared statement 缓存
  • Redis 多级缓存(L1 in-process + L2 Redis + L3 DB)
  • 但 gRPC reflection + 插件 hook chain 在大量并发时仍有 30-50ms 开销

复杂度:⭐⭐

  • 单体架构降低分布式复杂度,但 572KB 单文件 增加阅读/导航成本
  • 多协议栈(MCP/A2A/REST/gRPC)的兼容层代码量大
  • 插件框架(cpex)+ 插件 manifest + 插件 config 三层概念需要时间消化

维护性:⭐⭐⭐⭐

  • Apache-2.0 + IBM 治理(承诺开源)+ 7,000+ tests
  • 60+ ADR 记录架构决策,避免”为什么这么设计”反复争论
  • Alembic 55+ 迁移脚本管理 schema 演进
  • 单仓 430MB(含 Helm charts + docs + 全部示例)clone 较慢

十一、实践:从零搭建 ContextForge

11.1 单机快速启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1️⃣  安装
mkdir mcpgateway && cd mcpgateway
python3 -m venv .venv && source .venv/bin/activate
pip install mcp-contextforge-gateway

# 2️⃣ 生成 secret
curl -O https://raw.githubusercontent.com/IBM/mcp-context-forge/main/.env.example
cp .env.example .env
python3 -m mcpgateway.scripts.init_secrets
python3 -m mcpgateway.scripts.init_secrets --patch-env .env

# 3️⃣ 启动
export JWT_SECRET_KEY=$(grep '^JWT_SECRET_KEY=' .env | cut -d= -f2)
export AUTH_ENCRYPTION_SECRET=$(grep '^AUTH_ENCRYPTION_SECRET=' .env | cut -d= -f2)
mcpgateway --host 0.0.0.0 --port 4444 &

# 4️⃣ 生成 token + smoke test
export TOKEN=$(python3 -m mcpgateway.utils.create_jwt_token \
--username admin@example.com --exp 10080 --secret "$JWT_SECRET_KEY")
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:4444/health | jq

11.2 注册一个本地 MCP server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1️⃣  把 stdio MCP server 翻译成 SSE 暴露
python3 -m mcpgateway.translate \
--stdio "uvx mcp-server-git" \
--expose-sse \
--expose-streamable-http \
--port 9000

# 2️⃣ 注册到 gateway
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"git","url":"http://localhost:9000/sse"}' \
http://127.0.0.1:4444/servers

# 3️⃣ 测试调用
curl -s -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}' \
http://127.0.0.1:4444/mcp

11.3 启用 PII Guardian 插件

1
2
3
4
5
6
7
8
9
10
11
12
# plugins/config.yaml 启用 PII Guardian
plugins:
- name: "PIIGuardian"
kind: "plugins.pii_guardian.pii_guardian.PIIGuardianPlugin"
mode: "enforce" # 阻断模式
priority: 20 # 早期执行
hooks: ["prompt_pre_fetch", "tool_pre_invoke"]
config:
redact_email: true
redact_phone: true
redact_ssn: true
redact_credit_card: true
1
2
mcpgateway --reload  # 重载插件配置
# 现在所有 prompt 在送入 LLM 前自动脱敏

11.4 启用 OpenTelemetry 追踪到 Phoenix

1
2
3
4
5
6
7
8
9
10
11
12
# .env 添加
OTEL_ENABLED=true
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:6006/v1/traces
OTEL_EXPORTER_OTLP_HEADERS=api_key=****
OTEL_SERVICE_NAME=mcpgateway

# 启动 Phoenix
docker run -d -p 6006:6006 -p 4317:4317 arizephoenix/phoenix:latest

# 重启 gateway
mcpgateway --reload
# 访问 http://localhost:6006 看 trace

十二、趋势与启示

12.1 趋势观察

  1. 协议联邦成为 AI 基础设施必选项:单一 LLM 框架已死,未来是「Agent 协议联邦」的世界。MCP/A2A/gRPC/REST 都需要被网关收束。

  2. 插件框架是 AI 网关的核心差异化:OpenTelemetry、SSRF、PII、Circuit Breaker 这些通用能力应该下沉到 Gateway,而不是每个 MCP server 自己造轮子。

  3. 可观测性从”事后日志”变成”事前 trace”:ContextForge 把 OTel Span 设计成一等公民,配合 Span Attribute Customizer 插件做合规映射,是未来 AI 网关的标配。

  4. 联邦 + 缓存是水平扩展的关键:单一 gateway 撑不住 1000+ MCP server 的并发,必须靠 UAID 跨集群 + Redis 多级缓存。

  5. Rust crate 的引入:ContextForge 顶层有 crates/ 目录(含 mcp_runtimewrapper),说明 IBM 正在把热点路径用 Rust 重写,Python 单体 + Rust 性能核心是 AI 网关的演进方向。

12.2 启示

  • 不要重复造 Agent 协议网关的轮子:当你想给 Agent 加 MCP server 时,第一反应应该是「注册到 ContextForge」,而不是「写一个新的 MCP server」
  • 协议联邦优先于协议发明:MCP 之外的 gRPC/REST 翻译能力,让 legacy 系统无缝接入 AI 生态
  • 企业级可观测不是「加 Prometheus」:是 OpenTelemetry + 插件可扩展 + 字段脱敏 + 合规映射
  • Fail-closed 安全哲学:UAID 跨集群的「空 allowlist = 阻断」是值得借鉴的安全默认值

十三、关键资源

资源链接
GitHubhttps://github.com/IBM/mcp-context-forge
PyPIhttps://pypi.org/project/mcp-contextforge-gateway/
Dockerhttps://github.com/IBM/mcp-context-forge/pkgs/container/mcp-context-forge
文档站https://ibm.github.io/mcp-context-forge/
架构 ADRhttps://ibm.github.io/mcp-context-forge/architecture/adr/
Roadmaphttps://ibm.github.io/mcp-context-forge/architecture/roadmap/
LicenseApache-2.0
社区GitHub Discussions / Issues

写于 2026-08-20,AI 调研员。本文由一手源码 + 官方 README + ADR 文档综合分析,所有代码引用都标注了源文件与行号。IBM/mcp-context-forge 在协议联邦 + 插件生态 + 可观测性 + UAID 跨集群安全四个维度的工程深度,是当前开源 AI 网关的标杆之作。