<!-- title: MCP网关实战：多服务聚合到OAuth授权全链路 -->

# MCP网关实战：多服务聚合到OAuth 2.1授权全链路

## 概述

本教程面向有一定MCP Server开发基础、希望将多个MCP服务整合为统一入口并加上生产级授权保护的工程师。你将学会：搭建MCP网关聚合多个后端Server、实现OAuth 2.1 + PKCE授权流、在Claude Code中配置网关连接、以及网关层的路由与监控策略。学完即可在企业环境中部署带认证的MCP工具集群。

**适用人群**：已有MCP Server开发经验，需要多服务编排和安全加固的中高级开发者。

**预计教学时长**：3-4小时（含动手实验）。

## 前置条件

| 条件 | 说明 |
|------|------|
| Claude Code | 已安装并熟悉基本操作 |
| Node.js 20+ | 用于运行MCP Gateway和自建Server |
| Docker | 用于运行OAuth授权服务器（Keycloak/Auth0） |
| MCP基础 | 理解Tool、Resource、Prompt三种原语 |
| OAuth概念 | 了解授权码流程基本概念 |

## 第一部分：为什么需要MCP网关

### 单体Server的困境

当你的MCP生态从3个Server增长到20个时，问题接踵而至：

```
┌─────────────┐     ┌────────┐
│ Claude Code  │────→│Server A│ (GitHub)
│              │────→│Server B│ (数据库)
│              │────→│Server C│ (文件系统)
│              │────→│Server D│ (Slack)
│              │────→│Server E│ (Jira)
└─────────────┘     └────────┘
```

**痛点**：
- Claude Code的`.mcp.json`配置膨胀，每个Server一行命令
- 没有统一的认证入口，每个Server各自处理鉴权
- 无法在网关层做流量控制、审计日志、工具发现
- Server上下线需要修改每个客户端的配置

### 网关架构

引入MCP Gateway后：

```
┌─────────────┐     ┌──────────────┐     ┌────────┐
│ Claude Code  │────→│ MCP Gateway   │────→│Server A│
│ (单一入口)   │     │ (聚合+认证)   │────→│Server B│
│              │     │              │────→│Server C│
└─────────────┘     └──────────────┘     └────────┘
```

Claude Code只需连接一个Gateway，所有工具、资源、Prompt在Gateway内部聚合后统一暴露。

### 网关 vs 代理 vs Server

根据社区的定义，三者有清晰边界：

| 概念 | 职责 | 典型实现 |
|------|------|---------|
| **MCP Server** | 暴露具体工具，执行业务逻辑 | 你的自定义Server |
| **MCP Proxy** | 透传请求，可加认证头 | mcp-auth-proxy |
| **MCP Gateway** | 聚合多个Server、路由、认证、监控 | Microsoft MCP Gateway、Bifrost |

## 第二部分：实战一——用Microsoft MCP Gateway聚合多Server

Microsoft开源的`mcp-gateway`是目前最成熟的MCP网关实现，支持Kubernetes原生部署、会话感知路由和生命周期管理。

### 2.1 安装

```bash
# 方式一：npm全局安装
npm install -g @microsoft/mcp-gateway

# 方式二：Docker（推荐生产环境）
docker pull mcr.microsoft.com/mcp-gateway:latest

# 方式三：从源码编译
git clone https://github.com/microsoft/mcp-gateway.git
cd mcp-gateway
go build -o mcp-gateway ./cmd/gateway
```

### 2.2 编写网关配置

创建`gateway-config.yaml`：

```yaml
# gateway-config.yaml - MCP Gateway聚合配置
server:
  name: "enterprise-mcp-gateway"
  version: "1.0.0"
  transport: streamable-http  # 使用Streamable HTTP传输
  port: 8080

# 后端MCP Server列表
backends:
  - name: "github"
    transport: stdio
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-github"]
    env:
      GITHUB_PERSONAL_ACCESS_TOKEN: "${GITHUB_TOKEN}"
    
  - name: "filesystem"
    transport: stdio
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"]
    
  - name: "postgres"
    transport: stdio
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-postgres"]
    env:
      POSTGRES_CONNECTION_STRING: "${DATABASE_URL}"

  - name: "slack"
    transport: stdio
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-slack"]
    env:
      SLACK_BOT_TOKEN: "${SLACK_TOKEN}"

# 路由规则
routing:
  # 工具名称前缀路由
  tool_prefix:
    "github_*": "github"
    "fs_*": "filesystem"
    "db_*": "postgres"
    "slack_*": "slack"
  
  # 默认路由（无前缀匹配时）
  default: "github"

# 会话管理
session:
  ttl: 3600          # 会话超时1小时
  max_concurrent: 50  # 最大并发会话数
```

### 2.3 启动网关

```bash
# 设置环境变量
export GITHUB_TOKEN="ghp_xxxx"
export DATABASE_URL="postgresql://user:pass@localhost:5432/mydb"
export SLACK_TOKEN="xoxb-xxxx"

# 启动Gateway
mcp-gateway --config gateway-config.yaml
```

预期输出：

```
✓ MCP Gateway "enterprise-mcp-gateway" v1.0.0 started
✓ Transport: Streamable HTTP on :8080
✓ Registered 4 backends: github, filesystem, postgres, slack
✓ Aggregated 23 tools, 5 resources, 3 prompts
✓ Session TTL: 3600s, Max concurrent: 50
```

### 2.4 在Claude Code中连接网关

编辑`~/.claude.json`或项目级`.mcp.json`：

```json
{
  "mcpServers": {
    "enterprise-gateway": {
      "type": "streamable-http",
      "url": "http://localhost:8080/mcp"
    }
  }
}
```

验证连接：

```bash
claude mcp list
# 应输出 enterprise-gateway 的所有聚合工具

claude mcp tools enterprise-gateway
# 列出23个工具：github_create_issue, fs_read_file, db_query, slack_post_message...
```

### 2.5 常见问题

**Q：网关启动报"backend health check failed"**

```bash
# 检查后端Server是否可独立运行
npx -y @modelcontextprotocol/server-github --help

# 检查环境变量
echo $GITHUB_TOKEN
```

**Q：Claude Code连接网关超时**

```bash
# 检查端口是否开放
curl -v http://localhost:8080/mcp

# 检查防火墙规则
sudo ufw allow 8080/tcp
```

## 第三部分：实战二——OAuth 2.1授权层

MCP 2025-03-26规范引入了正式的授权框架，要求远程Server使用OAuth 2.1 + PKCE。网关是实施这一安全层的最佳位置。

### 3.1 MCP授权规范核心要点

```mermaid
sequenceDiagram
    participant CC as Claude Code<br/>(MCP Client)
    participant GW as MCP Gateway<br/>(Authorization Server)
    participant AS as OAuth Provider<br/>(Keycloak/Auth0)
    participant BS as Backend Server

    CC->>GW: 1. Initialize (无Token)
    GW->>CC: 2. 401 + WWW-Authenticate<br/>指示授权服务器地址
    CC->>AS: 3. GET /authorize<br/>+ code_challenge (PKCE)
    AS->>CC: 4. 登录页面
    CC->>AS: 5. 用户认证
    AS->>CC: 6. Authorization Code
    CC->>AS: 7. POST /token<br/>+ code_verifier
    AS->>CC: 8. Access Token + Refresh Token
    CC->>GW: 9. Initialize (Bearer Token)
    GW->>AS: 10. 验证Token (introspection)
    GW->>CC: 11. 连接建立
    CC->>GW: 12. Tool Call (带Token)
    GW->>BS: 13. 路由到后端
    BS->>GW: 14. 执行结果
    GW->>CC: 15. 返回结果
```

规范要求：
- **OAuth 2.1** 授权码流程（不是隐式流程）
- **PKCE**（Proof Key for Code Exchange）防止授权码截获
- **Dynamic Client Registration** (RFC 7591) 动态注册客户端
- **Token轮转** 刷新令牌必须单次使用
- **RFC 9728** 保护资源元数据发现

### 3.2 搭建OAuth Provider

使用Keycloak作为授权服务器（Docker一键部署）：

```bash
# 启动Keycloak
docker run -d \
  --name keycloak \
  -p 8180:8080 \
  -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
  -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
  quay.io/keycloak/keycloak:26.0 start-dev

# 等待启动完成
sleep 15

# 创建MCP Realm和Client
curl -s http://localhost:8180/realms/master/.well-known/openid-configuration | jq '.issuer'
# 输出: http://localhost:8180/realms/master
```

在Keycloak管理控制台（`http://localhost:8180`）中：
1. 创建新Realm：`mcp-realm`
2. 创建新Client：`mcp-gateway-client`
3. Client Authentication：开启（机密客户端）
4. Valid Redirect URIs：`http://localhost:8080/callback`
5. 在"Advanced"中启用"OAuth 2.0 Device Authorization Grant"

### 3.3 网关集成OAuth

更新`gateway-config.yaml`：

```yaml
# gateway-config.yaml - 带OAuth的完整配置
server:
  name: "enterprise-mcp-gateway"
  version: "1.0.0"
  transport: streamable-http
  port: 8080

# OAuth 2.1 授权配置
authorization:
  enabled: true
  provider: keycloak
  
  # 授权服务器端点（从.well-known自动发现）
  issuer: "http://localhost:8180/realms/mcp-realm"
  authorization_endpoint: "http://localhost:8180/realms/mcp-realm/protocol/openid-connect/auth"
  token_endpoint: "http://localhost:8180/realms/mcp-realm/protocol/openid-connect/token"
  jwks_uri: "http://localhost:8180/realms/mcp-realm/protocol/openid-connect/certs"
  
  # 客户端配置
  client_id: "mcp-gateway-client"
  client_secret: "${KEYCLOAK_CLIENT_SECRET}"
  
  # PKCE配置（必须启用）
  pkce:
    enabled: true
    method: "S256"    # SHA256哈希
  
  # Dynamic Client Registration
  dcr:
    enabled: true
    endpoint: "http://localhost:8180/realms/mcp-realm/clients-registrations/openid-connect"
  
  # Token策略
  tokens:
    access_token_ttl: 900      # 15分钟
    refresh_token_ttl: 86400   # 24小时
    refresh_token_rotation: true  # 单次使用
    
  # 资源元数据（RFC 9728）
  resource_metadata:
    resource_name: "Enterprise MCP Gateway"
    resource_uri: "http://localhost:8080/mcp"
    scopes_supported:
      - "tools:read"
      - "tools:execute"
      - "resources:read"
      - "admin"

# 后端Server（同上）
backends:
  - name: "github"
    transport: stdio
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-github"]
    env:
      GITHUB_PERSONAL_ACCESS_TOKEN: "${GITHUB_TOKEN}"
  - name: "filesystem"
    transport: stdio
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"]

# 基于Scope的访问控制
access_control:
  default_policy: "deny"
  rules:
    - scope: "tools:read"
      allow: ["tools/list"]
    - scope: "tools:execute"
      allow: ["tools/call"]
    - scope: "resources:read"
      allow: ["resources/list", "resources/read"]
    - scope: "admin"
      allow: ["*"]
```

### 3.4 Claude Code OAuth流程

启动网关后，Claude Code的连接流程：

```bash
# 1. Claude Code首次连接，触发OAuth
claude mcp add enterprise-gw --transport streamable-http --url http://localhost:8080/mcp

# 2. Claude Code自动检测到需要授权
# 输出类似：
# Authorization required. Opening browser...
# Please visit: http://localhost:8180/realms/mcp-realm/protocol/openid-connect/auth?client_id=mcp-gateway-client&code_challenge=xxx&redirect_uri=http://localhost:8080/callback

# 3. 浏览器打开Keycloak登录页，输入凭据

# 4. 授权成功，Token自动保存
# Token stored securely in keychain

# 5. 后续请求自动携带Token
claude mcp tools enterprise-gw
```

Claude Code内置了完整的OAuth 2.1客户端逻辑：
- 自动生成PKCE的`code_verifier`和`code_challenge`
- 支持Dynamic Client Registration
- Token自动刷新（使用refresh_token）
- Token安全存储（OS keychain集成）

### 3.5 Token管理细节

```bash
# 查看当前Token状态
claude mcp auth status enterprise-gw

# 输出：
# Server: enterprise-gateway
# Status: authenticated
# Access Token: expires in 12min 34s
# Refresh Token: expires in 23h 45min
# Scopes: tools:read tools:execute resources:read

# 强制重新认证
claude mcp auth login enterprise-gw

# 登出（清除Token）
claude mcp auth logout enterprise-gw
```

## 第四部分：实战三——轻量级mcp-auth-proxy

如果你的场景不需要完整的网关聚合，只需要给现有Server加一层OAuth认证，`mcp-auth-proxy`是更轻量的选择。

### 4.1 安装与配置

```bash
git clone https://github.com/sigbit/mcp-auth-proxy.git
cd mcp-auth-proxy
npm install
```

创建`auth-proxy-config.json`：

```json
{
  "port": 9090,
  "target": {
    "transport": "stdio",
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-github"]
  },
  "auth": {
    "type": "oauth21",
    "issuer": "http://localhost:8180/realms/mcp-realm",
    "audience": "mcp-github-api",
    "scopes": ["tools:read", "tools:execute"]
  }
}
```

```bash
# 启动代理
node dist/index.js --config auth-proxy-config.json
```

这相当于在你的MCP Server前面加了一个认证反向代理——所有请求必须携带有效Token才能到达后端。

### 4.2 架构对比

```mermaid
graph TB
    subgraph "方案A：完整网关"
        CC1[Claude Code] --> GW[MCP Gateway<br/>聚合+认证+路由]
        GW --> S1[Server A]
        GW --> S2[Server B]
        GW --> S3[Server C]
        GW --> OAuth1[OAuth Provider]
    end

    subgraph "方案B：认证代理"
        CC2[Claude Code] --> AP[Auth Proxy<br/>仅认证]
        AP --> S4[单个Server]
        AP --> OAuth2[OAuth Provider]
    end

    style GW fill:#4a9eff,color:#fff
    style AP fill:#ff9f43,color:#fff
```

| 维度 | MCP Gateway | Auth Proxy |
|------|------------|------------|
| 聚合多Server | 支持 | 不支持 |
| OAuth认证 | 支持 | 支持 |
| 路由规则 | 前缀/正则/权重 | 无 |
| 会话管理 | 有 | 无 |
| 适用场景 | 多Server集群 | 单Server加固 |

## 第五部分：实战四——Bifrost网关的高级模式

Bifrost是Maxim AI开源的企业级AI网关，支持MCP协议，提供负载均衡、限流、可观测性等高级功能。

### 5.1 Docker Compose全栈部署

创建`docker-compose.yml`：

```yaml
version: '3.8'

services:
  # OAuth授权服务器
  keycloak:
    image: quay.io/keycloak/keycloak:26.0
    environment:
      KC_BOOTSTRAP_ADMIN_USERNAME: admin
      KC_BOOTSTRAP_ADMIN_PASSWORD: admin
    ports:
      - "8180:8080"
    command: start-dev

  # MCP Gateway
  bifrost:
    image: ghcr.io/maximhq/bifrost:latest
    ports:
      - "8080:8080"
    environment:
      # Gateway配置
      BIFROST_MCP_ENABLED: "true"
      BIFROST_MCP_PORT: "8080"
      
      # 后端MCP Server
      BIFROST_MCP_SERVERS: |
        github:
          transport: stdio
          command: npx
          args: ["-y", "@modelcontextprotocol/server-github"]
          env:
            GITHUB_PERSONAL_ACCESS_TOKEN: ${GITHUB_TOKEN}
        filesystem:
          transport: stdio
          command: npx
          args: ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
          
      # OAuth配置
      BIFROST_AUTH_PROVIDER: keycloak
      BIFROST_AUTH_ISSUER: http://keycloak:8080/realms/mcp-realm
      BIFROST_AUTH_CLIENT_ID: bifrost-mcp
      
      # 限流配置
      BIFROST_RATE_LIMIT_RPM: 60
      BIFROST_RATE_LIMIT_BURST: 10
      
      # 日志级别
      BIFROST_LOG_LEVEL: info
    volumes:
      - ./data:/data
    depends_on:
      - keycloak

  # 可选：Prometheus监控
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
```

启动：

```bash
export GITHUB_TOKEN="ghp_xxxx"
docker compose up -d

# 查看日志
docker compose logs -f bifrost
```

### 5.2 Claude Code连接配置

```json
{
  "mcpServers": {
    "bifrost-gateway": {
      "type": "streamable-http",
      "url": "http://localhost:8080/mcp",
      "headers": {
        "Authorization": "Bearer ${BIFROST_TOKEN}"
      }
    }
  }
}
```

## 第六部分：网关层的高级模式

### 6.1 基于Scope的工具过滤

Gateway可以根据用户的OAuth Scope动态过滤可用工具：

```yaml
# 在gateway-config.yaml中配置
access_control:
  tool_filters:
    - match: "github_*"
      required_scopes: ["tools:execute"]
    - match: "db_*"
      required_scopes: ["tools:execute", "admin"]
    - match: "fs_*"
      required_scopes: ["tools:read"]
```

效果：一个只有`tools:read` Scope的用户调用`tools/list`时，只能看到`fs_*`系列工具，`github_*`和`db_*`完全不可见。

### 6.2 审计日志

在网关层记录所有工具调用的审计日志：

```yaml
logging:
  audit:
    enabled: true
    format: json
    output: /var/log/mcp-gateway/audit.log
    fields:
      - timestamp
      - session_id
      - user_id        # 从Token中提取
      - tool_name
      - backend_name
      - duration_ms
      - status         # success/error
```

日志示例：

```json
{
  "timestamp": "2026-05-29T10:30:45.123Z",
  "session_id": "sess_abc123",
  "user_id": "alice@example.com",
  "tool_name": "github_create_issue",
  "backend_name": "github",
  "duration_ms": 342,
  "status": "success"
}
```

### 6.3 熔断与降级

```yaml
resilience:
  circuit_breaker:
    enabled: true
    failure_threshold: 5      # 连续5次失败后熔断
    recovery_timeout: 30      # 30秒后半开
    half_open_max_calls: 3    # 半开状态允许3个测试请求
    
  rate_limiting:
    enabled: true
    requests_per_minute: 60
    burst: 10
    
  timeout:
    tool_call: 30000          # 工具调用超时30秒
    initialization: 10000     # 初始化超时10秒
    
  fallback:
    # 后端不可用时的降级策略
    github: "cached_response" # 返回缓存
    postgres: "error_message" # 返回明确错误
```

## 第七部分：完整实战项目——带认证的企业MCP工具平台

### 7.1 项目架构

```mermaid
graph TB
    subgraph "客户端层"
        CC[Claude Code<br/>CLI]
        CD[Claude Desktop<br/>GUI]
        CI[CI/CD Pipeline<br/>GitHub Actions]
    end

    subgraph "网关层"
        GW[MCP Gateway<br/>:8080]
        AUTH[OAuth 2.1<br/>授权模块]
        RL[Rate Limiter<br/>限流]
        AUDIT[Audit Logger<br/>审计]
    end

    subgraph "OAuth Provider"
        KC[Keycloak<br/>:8180]
    end

    subgraph "后端Server集群"
        GH[GitHub Server]
        FS[Filesystem Server]
        DB[Postgres Server]
        SL[Slack Server]
        CUSTOM[自建业务Server]
    end

    CC -->|Streamable HTTP| GW
    CD -->|Streamable HTTP| GW
    CI -->|Bearer Token| GW

    GW --> AUTH
    GW --> RL
    GW --> AUDIT
    AUTH --> KC

    GW --> GH
    GW --> FS
    GW --> DB
    GW --> SL
    GW --> CUSTOM

    style GW fill:#4a9eff,color:#fff
    style AUTH fill:#ff6b6b,color:#fff
    style KC fill:#ffd93d,color:#333
```

### 7.2 完整部署脚本

创建`deploy.sh`：

```bash
#!/bin/bash
set -euo pipefail

echo "=== MCP Gateway 企业部署 ==="

# 1. 检查依赖
command -v docker >/dev/null 2>&1 || { echo "需要Docker"; exit 1; }
command -v node >/dev/null 2>&1 || { echo "需要Node.js 20+"; exit 1; }

# 2. 创建配置目录
mkdir -p config logs data

# 3. 生成PKCE密钥对（用于Keycloak Client配置）
CODE_VERIFIER=$(openssl rand -base64 32 | tr -d '=/+')
CODE_CHALLENGE=$(echo -n "$CODE_VERIFIER" | openssl dgst -sha256 -binary | base64 | tr '+/' '-_' | tr -d '=')
echo "PKCE Code Verifier: $CODE_VERIFIER"
echo "PKCE Code Challenge: $CODE_CHALLENGE"

# 4. 启动Keycloak
docker run -d \
  --name mcp-keycloak \
  -p 8180:8080 \
  -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
  -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
  -e KEYCLOAK_ADMIN=admin \
  -e KEYCLOAK_ADMIN_PASSWORD=admin \
  quay.io/keycloak/keycloak:26.0 start-dev

echo "等待Keycloak启动..."
sleep 20

# 5. 配置Keycloak Realm
# 获取Admin Token
ADMIN_TOKEN=$(curl -s -X POST \
  http://localhost:8180/realms/master/protocol/openid-connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=admin&password=admin&grant_type=password&client_id=admin-cli" \
  | jq -r '.access_token')

# 创建Realm
curl -s -X POST http://localhost:8180/admin/realms \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "realm": "mcp-realm",
    "enabled": true
  }'

# 创建Client
curl -s -X POST http://localhost:8180/admin/realms/mcp-realm/clients \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "mcp-gateway-client",
    "enabled": true,
    "clientAuthenticatorType": "client-secret",
    "redirectUris": ["http://localhost:8080/callback"],
    "webOrigins": ["+"],
    "standardFlowEnabled": true,
    "publicClient": false,
    "attributes": {
      "oauth2.device.authorization.grant.enabled": "true",
      "pkce.code.challenge.method": "S256"
    }
  }'

# 获取Client Secret
CLIENT_UUID=$(curl -s http://localhost:8180/admin/realms/mcp-realm/clients?clientId=mcp-gateway-client \
  -H "Authorization: Bearer $ADMIN_TOKEN" | jq -r '.[0].id')

CLIENT_SECRET=$(curl -s http://localhost:8180/admin/realms/mcp-realm/clients/$CLIENT_UUID/client-secret \
  -X POST \
  -H "Authorization: Bearer $ADMIN_TOKEN" | jq -r '.value')

echo "Client Secret: $CLIENT_SECRET"

# 创建测试用户
curl -s -X POST http://localhost:8180/admin/realms/mcp-realm/users \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "mcp-user",
    "enabled": true,
    "email": "mcp@example.com",
    "credentials": [{"type": "password", "value": "password123", "temporary": false}]
  }'

echo "Keycloak配置完成"

# 6. 创建Gateway配置
cat > config/gateway-config.yaml << EOF
server:
  name: "enterprise-mcp-gateway"
  version: "1.0.0"
  transport: streamable-http
  port: 8080

authorization:
  enabled: true
  issuer: "http://localhost:8180/realms/mcp-realm"
  client_id: "mcp-gateway-client"
  client_secret: "${CLIENT_SECRET}"
  pkce:
    enabled: true
    method: "S256"

backends:
  - name: "github"
    transport: stdio
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-github"]
  - name: "filesystem"
    transport: stdio
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-filesystem", "${PWD}/data"]

logging:
  audit:
    enabled: true
    format: json
    output: "${PWD}/logs/audit.log"
EOF

echo "配置文件已生成：config/gateway-config.yaml"
echo ""
echo "下一步："
echo "  1. export GITHUB_TOKEN=ghp_xxxx"
echo "  2. mcp-gateway --config config/gateway-config.yaml"
echo "  3. claude mcp add enterprise --transport streamable-http --url http://localhost:8080/mcp"
```

### 7.3 验证全链路

```bash
# 1. 运行部署脚本
chmod +x deploy.sh
./deploy.sh

# 2. 设置Token并启动Gateway
export GITHUB_TOKEN="ghp_your_token_here"
mcp-gateway --config config/gateway-config.yaml

# 3. 在另一个终端，添加MCP Server到Claude Code
claude mcp add enterprise --transport streamable-http --url http://localhost:8080/mcp

# 4. Claude Code自动触发OAuth流程
# 浏览器打开Keycloak登录页 → 输入 mcp-user / password123

# 5. 验证工具可用
claude mcp tools enterprise

# 6. 测试工具调用（带认证）
claude -p "列出GitHub仓库中的issues" --mcp enterprise

# 7. 查看审计日志
tail -f logs/audit.log | jq .
```

## 第八部分：Envoy AI Gateway方案（云原生）

如果你的基础设施基于Kubernetes，Envoy AI Gateway提供了另一种网关选择。它作为Envoy代理的扩展，原生支持MCP聚合。

### 8.1 架构

```
┌──────────┐     ┌───────────────┐     ┌──────────────┐
│Claude Code│────→│ Envoy Proxy    │────→│ MCP Server A │
│           │     │ + AI Gateway   │────→│ MCP Server B │
│           │     │ extension      │────→│ MCP Server C │
└──────────┘     └───────────────┘     └──────────────┘
```

核心特性：
- 将多个MCP Server聚合为单一端点
- 支持LLM路由（多模型切换）
- Kubernetes Gateway API兼容
- 原生支持速率限制和认证

### 8.2 快速部署

```yaml
# envoy-ai-gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: mcp-aggregate
spec:
  parentRefs:
    - name: ai-gateway
  rules:
    - backendRefs:
        - name: mcp-github
          port: 3000
        - name: mcp-filesystem
          port: 3000
        - name: mcp-postgres
          port: 3000
      filters:
        - type: MCPAggregation
```

## 第九部分：生产环境检查清单

部署带OAuth的MCP Gateway到生产环境前，逐项确认：

### 安全

- [ ] OAuth 2.1 + PKCE已启用（不是OAuth 2.0）
- [ ] Refresh Token轮转开启（单次使用）
- [ ] Access Token有效期 ≤ 15分钟
- [ ] 使用HTTPS/TLS加密所有通信
- [ ] Client Secret存储在密钥管理服务（非环境变量明文）
- [ ] 后端Server不直接暴露端口（仅Gateway可达）
- [ ] CORS配置严格限定域名

### 可靠性

- [ ] 熔断器配置合理（5次失败触发，30秒恢复）
- [ ] 工具调用超时 ≤ 30秒
- [ ] 限流阈值根据业务峰值设定
- [ ] 后端Server健康检查间隔 ≤ 10秒
- [ ] 降级策略已定义（缓存/错误/排队）

### 可观测性

- [ ] 审计日志记录所有工具调用
- [ ] Prometheus指标暴露（请求延迟、错误率、Token使用）
- [ ] 结构化日志（JSON格式）
- [ ] 链路追踪（可选，OpenTelemetry集成）
- [ ] 告警规则（错误率 > 5%触发）

### 运维

- [ ] 配置文件版本控制（不含Secret）
- [ ] Docker镜像使用固定版本标签
- [ ] 滚动更新策略已测试
- [ ] 备份Keycloak Realm配置
- [ ] Token撤销流程已验证

## 工作流总结

```mermaid
flowchart LR
    A[开发MCP Server] --> B[本地测试]
    B --> C[部署到网关后端]
    C --> D[配置OAuth Provider]
    D --> E[网关集成认证]
    E --> F[Claude Code连接测试]
    F --> G[生产环境部署]
    G --> H[监控与审计]

    B -->|失败| I[调试修复]
    I --> B
    F -->|Token过期| J[自动刷新]
    J --> F

    style A fill:#e3f2fd
    style E fill:#fff3e0
    style G fill:#e8f5e9
    style H fill:#fce4ec
```

## 训练营适用性评估

| 训练营类型 | 适合度 | 说明 |
|-----------|--------|------|
| 企业MCP平台搭建 | 极高 | 直接对应生产级需求 |
| AI Agent安全工程 | 高 | OAuth 2.1实战是核心内容 |
| 云原生AI工具链 | 高 | K8s部署、Envoy网关均有覆盖 |
| MCP Server初学者 | 低 | 需要先掌握基础Server开发 |
| 前端/全栈开发 | 中低 | 偏后端基础设施 |

**教学时长**：3-4小时，其中：
- 网关搭建与聚合：1小时
- OAuth 2.1授权集成：1.5小时
- 完整项目部署与验证：1小时
- 故障排查与Q&A：0.5小时

## 参考来源

1. [MCP Authorization Specification](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization) — MCP官方授权规范，定义OAuth 2.1在MCP中的使用方式
2. [Microsoft MCP Gateway](https://github.com/microsoft/mcp-gateway) — 微软开源的MCP反向代理与网关实现
3. [MCP Gateway & Proxy Patterns](https://chatforest.com/guides/mcp-gateway-proxy-patterns/) — 网关与代理架构模式深度解析
4. [MCP OAuth 2.1 Complete Guide](https://dev.to/composiodev/mcp-oauth-21-a-complete-guide-3g91) — OAuth 2.1在MCP中的完整实现指南
5. [Red Hat: Advanced Auth for MCP Gateway](https://developers.redhat.com/articles/2025/12/12/advanced-authentication-authorization-mcp-gateway) — 企业级MCP网关认证授权方案
6. [Claude Code MCP Documentation](https://code.claude.com/docs/en/mcp) — Claude Code连接MCP Server的官方文档

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
