🔀 MCP YARP网关
Azure Kubernetes服务上模型上下文协议流量的安全反向代理
MCP YARP网关在AKS上提供了一条面向生产的MCP访问路径,Microsoft Foundry代理通过一个硬化的YARP代理层与后端MCP工具服务器进行通信,从而强制执行API密钥身份验证并保留HTTP流行为。
流量: 微软Foundry代理→ YARP代理(API密钥授权)→ MongoDB MCP服务器(HTTP传输)→ Azure Cosmos DB for MongoDB(文档数据库)
______________________________________________________________________
🎯 概述
该项目使用YARP反向代理作为经过身份验证的网关,保护和标准化AKS上的MCP HTTP流量。不是直接公开MCP工具服务器,而是通过代理路由所有代理通信,代理强制执行API密钥身份验证并将请求转发到内部MCP服务。
关键能力:
- YARP反向代理对所有MCP流量强制执行API密钥身份验证
- MongoDB MCP服务器在KS中运行,采用HTTP传输(仅限内部ClusterIP)
- Azure Cosmos DB for MongoDB(DocumentDB)作为备份数据存储
- 通过代理MCP端点集成Microsoft Foundry代理
- 用于用测试数据填充DocumentDB的合成数据种子器
- 通过Helm charts进行Kubernetes本地部署
- Azure本机基础架构配备了二头肌
______________________________________________________________________
📐 建筑
flowchart TD
KV["🔐 Azure Key Vault
Proxy API key · Connection strings"]
COSMOS["☁️ MongoDB (DocumentDB)"]
subgraph FOUNDRY["Microsoft Foundry"]
AGENT["🤖 Foundry Agent"]
TOOL["🔌 Foundry MCP Tool
Custom Tool (Key-based)"]
end
subgraph AKS["☸️ AKS Cluster"]
YARP["🔀 YARP Proxy
API key auth · Port 80"]
MCP["🗄️ MongoDB MCP Server
StatefulSet · HTTP transport · Port 3000
Headless Service (internal only)"]
SEEDER["🌱 Data Seeder
Synthetic data writer"]
end
AGENT --> TOOL
TOOL -->|"MCP HTTP + API key header"| YARP
YARP -->|"Unauthorized → 401"| TOOL
YARP -->|"Forwards authenticated requests"| MCP
MCP -->|"MDB_MCP_CONNECTION_STRING"| COSMOS
SEEDER -->|"Writes synthetic data"| COSMOS
KV -->|"Secrets injected at runtime"| YARP & MCPMCP会话关联
当MongoDB MCP服务器扩展到多个副本时,MCP会话必须固定到创建它们的pod上,否则后续请求将返回 404, 500.YARP使用自定义 McpSessionId 由具有每pod DNS路由的StatefulSet支持的关联策略。
sequenceDiagram
participant Agent as Microsoft Foundry Agent
participant LB as K8s LoadBalancer
participant YARP as YARP Proxy (any replica)
participant Pod0 as MCP Pod-0
participant Pod1 as MCP Pod-1
participant Pod2 as MCP Pod-2
Note over Agent,Pod2: 1️⃣ First request — no Mcp-Session-Id header
Agent->>LB: POST /mcp (no session ID)
LB->>YARP: Route to any YARP replica
YARP->>Pod1: LB picks Pod-1 (dest D2)
Pod1-->>YARP: 200 OK + Mcp-Session-Id: abc123
Note over YARP: AffinitizeResponse encodes:
D2.abc123
YARP-->>Agent: 200 OK + Mcp-Session-Id: D2.abc123
Note over Agent,Pod2: 2️⃣ Subsequent request — any YARP replica can route
Agent->>LB: POST /mcp + Mcp-Session-Id: D2.abc123
LB->>YARP: Route to any YARP replica
Note over YARP: Parse prefix D2 → route to dest D2
Restore header to abc123
YARP->>Pod1: Routed directly to Pod-1
Pod1-->>YARP: 200 OK
YARP-->>Agent: 200 OK关键设计决策:
| 问题 | 解决方案 |
|---|---|
| 稳定的每吊舱DNS | StatefulSet+headless Service为每个pod提供了一个可预测的地址 |
| 会话→ Pod映射 | 无状态:目标ID编码到 Mcp-Session-Id 头球D2.abc123) |
| 多YARP副本支持 | 完全无状态——任何YARP副本都可以正确解析标头和路由 |
| 吊舱故障 | 在群集中找不到目标→ YARP重新分配;MCP客户端重新初始化 |
核心组件
| 组件 | 技术 | 角色 |
|---|---|---|
| YARP代理 | .NET 8,YARP | neneneba API密钥强制执行,HTTP请求转发,MCP会话亲和性 |
| MongoDB MCP服务器 | Node.js、MCP SDK | 基于HTTP传输的MCP工具服务器 |
| Azure Cosmos DB for MongoDB | Azure PaaS | DocumentDB后台存储(DocumentDB API) |
| 数据种子 | Python | 连续合成数据编写器 |
| 微软Foundry代理 | Microsoft Foundry | 通过代理使用MCP工具的AI代理 |
______________________________________________________________________
📁 项目结构
Expand to view repository layout
mcp-yarp-gateway/
├── deploy.ps1 # Full end-to-end deployment orchestrator
├── README.md # This file
│
├── apps/
│ ├── yarp-proxy/ # .NET 8 YARP reverse proxy
│ │ ├── Program.cs # Entry point, middleware, proxy config
│ │ ├── McpSessionAffinityPolicy.cs # Custom YARP session affinity (MCP session → pod pinning)
│ │ ├── Proxy.csproj
│ │ ├── appsettings.json # Proxy routes, cluster destinations, auth config
│ │ ├── appsettings.Development.json
│ │ └── Dockerfile
│ └── data-seeder/ # Python synthetic data seeder
│ ├── src/
│ │ └── generator.py # Data generation logic
│ └── Dockerfile
│
├── infra/ # Infrastructure as Code (Bicep)
│ ├── main.bicep # Subscription-scoped main template
│ └── core/
│ ├── ai/ # Microsoft Foundry (account, project, models)
│ ├── data/
│ │ └── mongodb/ # Cosmos DB for MongoDB
│ ├── monitor/ # Log Analytics, App Insights
│ ├── platform/ # AKS, Container Registry
│ └── security/ # Key Vault, Managed Identity, RBAC
│
├── k8s/helm/
│ ├── mcp-tools/ # Namespace bootstrap (creates tools namespace)
│ ├── yarp-proxy/ # YARP proxy Helm chart (port 80)
│ ├── mongodb-mcp-server/ # MongoDB MCP server chart (internal, port 3000)
│ ├── data-seeder/ # Synthetic data seeder chart
│ └── platform/ # Shared platform resources (Prometheus, Grafana)
│
└── scripts/
├── Deploy-Infrastructure.ps1 # Phase 1: Bicep infra deployment
├── Deploy-Containers.ps1 # Phase 2: ACR image build & push
├── Deploy-Kubernetes.ps1 # Phase 3: Helm chart deployments
├── Deploy-FoundryAgents.ps1 # Phase 4: Microsoft Foundry agent setup
└── common/
└── DeploymentFunctions.psm1 # Shared PowerShell utilities______________________________________________________________________
🚀 部署
先决条件
| 工具 | 版本 | 注释 |
|---|---|---|
| Azure CLI | 最新版本 | az login 已认证 |
| PowerShell | 7+ | 部署脚本需要 |
| Helm | 3+ | Kubernetes部署需要 |
| Azure订阅 | -- | AKS、Cosmos DB、Microsoft Foundry、ACR的足够配额 |
本地不需要Docker——容器映像通过以下方式在Azure容器注册表中构建 az acr build.1.克隆存储库
git clone https://github.com/jonathanscholtes/mcp-yarp-gateway.git
cd mcp-yarp-gateway2.部署一切(单一命令)
az login
az account set --subscription "YOUR-SUBSCRIPTION-ID"
.\deploy.ps1 `
-Subscription "YOUR-SUBSCRIPTION-ID" `
-Location "eastus2" `
-UserObjectId "YOUR-AAD-OBJECT-ID" `
-AILocation 'westus3' [optional]通过以下方式获取您的对象ID:
az ad signed-in-user show --query id -o tsv部署会自动运行四个阶段:
| 阶段 | 脚本 | 它的作用 |
|---|---|---|
| 1--基础设施 | Deploy-Infrastructure.ps1 | 通过二头肌创建所有Azure资源 |
| 2--容器图像 | Deploy-Containers.ps1 | 构建代理和种子映像并将其推送到ACR |
| 3-库贝内特斯 | Deploy-Kubernetes.ps1 | 将Helm charts部署到AKS |
| 4--铸造代理 | Deploy-FoundryAgents.ps1 | 配置Microsoft Foundry代理 |
创建的资源(~15-20分钟):
- Azure Kubernetes服务(AKS)集群
- Azure容器注册表(代理+种子映像)
- Azure Cosmos DB for MongoDB(DocumentDB备份存储)
- Azure密钥库+托管身份(全程无秘密身份验证)
- Microsoft Foundry(帐户、项目、模型部署)
- 日志分析工作区+应用洞察
______________________________________________________________________
🔧 配置
Expand to view environment variable reference
YARP代理设置
| 变量 | 默认值 | 描述 |
|---|---|---|
Proxy:ApiKeyHeader / PROXY__APIKEYHEADER | api-key | 已检查API键的标头名称 |
Proxy:ApiKey / PROXY__APIKEY | - | 预期API密钥值(来自密钥库) |
Proxy:UpstreamTimeoutMinutes / PROXY__UPSTREAMTIMEOUTMINUTES | 5 | 上游MCP呼叫超时 |
ReverseProxy:Clusters:mcp-cluster:Destinations:d1:Address | -- | MCP服务器pod 0的每个pod URL |
ReverseProxy:Clusters:mcp-cluster:Destinations:d2:Address | -- | MCP服务器pod 1的每个pod URL |
ReverseProxy:Clusters:mcp-cluster:Destinations:d3:Address | -- | MCP服务器pod 2的每个pod URL |
MongoDB MCP服务器设置
| 变量 | 默认值 | 描述 |
|---|---|---|
MDB_MCP_CONNECTION_STRING | -- | DocumentDB连接字符串(来自密钥库) |
MDB_MCP_TRANSPORT | http | 运输方式(http 用于代理连接) |
MDB_MCP_HTTP_HOST | 0.0.0.0 | 绑定主机 |
MDB_MCP_HTTP_PORT | 3000 | 服务端口 |
MDB_MCP_READ_ONLY | true | 仅限于只读MCP工具(推荐) |
MDB_MCP_DISABLED_TOOLS | -- | 以逗号分隔的禁用工具列表 |
MDB_MCP_TELEMETRY | -- | 设置为 disabled 如果政策要求 |
代理/笔记本变量
| 变量 | 描述 |
|---|---|
PROJECT_ENDPOINT | Microsoft Foundry项目端点URL |
MODEL_DEPLOYMENT_NAME | 模型部署名称 |
MCP_SERVER_LABEL | MCP服务器注册标签 |
MCP_SERVER_URL | 设置为YARP代理端点(不是直接设置MongoDB MCP) |
使用AKS、Cosmos DB和密钥库进行身份验证 管理身份 --仓库中没有提交连接字符串或机密。
______________________________________________________________________
🔐 安全模型
- 代理只与YARP代理端点通信,从不直接与MCP服务器通信。
- YARP对每个请求强制执行API密钥头,并返回
401未经授权的呼叫。 - MongoDB MCP服务器未暴露在互联网上;它只能从群集中访问。
- 秘密在运行时从Azure密钥库注入——没有提交给源代码管理的凭据。
- TLS终止在入口/网关层处理。
______________________________________________________________________
✅ 验证清单
- \[\]YARP代理pod健康,正在为
/mcp/*路线 - \[\]启用HTTP传输后,MongoDB MCP服务器pod运行正常
- \[ \]
MDB_MCP_CONNECTION_STRING解析并连接到DocumentDB - \[\]未经授权的代理调用返回
401 - \[\]授权代理调用返回成功的MCP响应
- \[\]使用代理URL和可用的预期工具,AI Foundry代理运行成功
______________________________________________________________________
🔌 部署后:添加Foundry MCP连接
部署完成后,将YARP代理注册为Foundry项目中的自定义MCP工具,以便代理可以访问它。YARP代理外部IP和API密钥打印在 deploy.ps1.
- 在中打开您的Foundry项目 ai.ai.com.
- 首选 构建→ Tools (或打开 代理构建器).
- 选择 添加工具→ 自定义→ 模型上下文协议.
- 输入以下详细信息:
| 字段 | 值 |
|---|---|
| 姓名 | yarp-proxy-mcp |
| 远程MCP服务器端点 | http:///mcp |
| 身份验证 | 基于密钥 |
| 凭证 | `"api-key": " |
| "` |
- 选择 连接.
有关连接自定义MCP工具的完整详细信息,请参阅 使用自定义MCP工具连接.
______________________________________________________________________
♻️ 清理
完成测试后或不再需要时,请确保删除任何未使用的Azure资源或删除整个资源组,以避免额外费用。
______________________________________________________________________
📜 许可证
该项目根据 MIT许可证.
______________________________________________________________________
⚠️ 免责声明
此代码仅用于教育和演示目的。
此示例代码不用于生产用途,按“原样”提供,不提供任何明示或暗示的保证,包括但不限于适销性、特定用途适用性和不侵权保证。在任何情况下,作者或版权持有人均不对因软件或软件的使用或其他交易而产生、产生或与之相关的任何索赔、损害赔偿或其他责任承担责任,无论是在合同、侵权或其他诉讼中。
要点:
- 这是一个 示范项目 展示自主代理架构模式
- 不用于生产 无需进行额外的开发、测试和合规性审查
- 计算是简化模型,仅用于演示目的
- 用户有责任确保遵守适用的法规和安全要求
- Microsoft Azure服务会产生成本-监控您的使用情况并在完成时清理资源
- 对于准确性、可靠性或适用于任何目的,不提供任何保证或担保
通过使用此代码,您承认您理解这些限制,并对使用此代码的任何后果承担全部责任。
