GKE上具有工作负载身份联合(WIF)的MCP服务器

概述
概念证明,证明:
- Kubernetes上的MCP -在GKE上运行模型上下文协议服务器
- 工作负载身份联合 -从GitHub Actions到GCP的无密钥身份验证(无服务帐户密钥)
- MCP-UI -丰富的交互式界面,而不是原始的JSON响应
为什么选择MCP-UI?
文本非常适合简单的确认。这对天气预报、数据表或任何需要视觉结构的东西来说都是可怕的。MCP-UI允许服务器返回直接在聊天窗口中呈现的HTML接口——在正确的时间以正确的输出格式呈现。
看 docs/MCP_UI.md 了解实施细节。
堆栈
Python 3.12•Starlette•FastMCP•MCP-UI•GKE•GitHub Actions OIDC
项目结构
├── .github/workflows/
│ └── deploy.yml # CI/CD Pipeline definition
├── k8s/
│ └── deployment.yml # Kubernetes Deployment & Service manifests
├── src/
│ └── main.py # Application entrypoint & logic
├── Dockerfile # Multi-stage build instruction
├── pyproject.toml # Dependencies managed by uv
└── uv.lock # Exact versions for reproducibility
## Prerequisites
uv: Our chosen Python package manager. It replaces pip, poetry, and venv.
macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
Google Cloud CLI:用于与GCP资源交互。
## Docker:用于本地容器构建和测试
基础架构设置(Bootstrap)
要配置所需的基础设施(GKE集群、工件注册表和工作负载标识),请在Google Cloud Shell中运行以下脚本。
先决条件:确保您已创建GCP项目并启用了计费。
## 提供资源
将此块复制并粘贴到您的Cloud Shell终端中。它将自动检测项目ID,并等效地提供所有必要的资源。
--- CONFIGURATION ---
export PROJECT_ID=$(gcloud config get-value project) export REGION="europe-west2" export CLUSTER_NAME="mcp-cluster" export REPO_NAME="mcp-repo" export SA_NAME="github-actions-sa" export POOL_NAME="github-pool-v2" export PROVIDER_NAME="github-provider-v2" export USER_GITHUB="ettysekhon" # /dev/null 2>&1; then gcloud artifacts repositories create $REPO_NAME --repository-format=docker --location=$REGION --description="Docker repository for MCP Server" fi
3. Create GKE Cluster
if ! gcloud container clusters describe $CLUSTER_NAME --location=$REGION > /dev/null 2>&1; then echo "Creating GKE Cluster (approx 5-8 mins)..." gcloud container clusters create-auto $CLUSTER_NAME --location=$REGION fi
4. Configure Identity & Security
if ! gcloud iam service-accounts describe "$SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" > /dev/null 2>&1; then gcloud iam service-accounts create $SA_NAME --display-name="GitHub Actions Deployer" fi
Grant Roles
gcloud artifacts repositories add-iam-policy-binding $REPO_NAME --location=$REGION --member="serviceAccount:$SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" --role="roles/artifactregistry.writer" gcloud projects add-iam-policy-binding $PROJECT_ID --member="serviceAccount:$SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" --role="roles/container.developer"
Setup Workload Identity Federation
if ! gcloud iam workload-identity-pools describe $POOL_NAME --location="global" > /dev/null 2>&1; then gcloud iam workload-identity-pools create $POOL_NAME --location="global" --display-name="GitHub Actions Pool V2" fi
if ! gcloud iam workload-identity-pools providers describe $PROVIDER_NAME --location="global" --workload-identity-pool=$POOL_NAME > /dev/null 2>&1; then gcloud iam workload-identity-pools providers create-oidc $PROVIDER_NAME --location="global" --workload-identity-pool=$POOL_NAME --display-name="GitHub Provider" --issuer-uri="" --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" --attribute-condition="assertion.repository_owner == '${USER_GITHUB}'" fi
Link GitHub Repo to Service Account
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)") gcloud iam service-accounts add-iam-policy-binding "$SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" --role="roles/iam.workloadIdentityUser" --member="principalSet://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_NAME/attribute.repository_owner/${USER_GITHUB}"
echo "" echo "SETUP COMPLETE. Add these to GitHub Secrets:" echo "---------------------------------------------------" echo "GCP_WIF_PROVIDER: projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_NAME/providers/$PROVIDER_NAME" echo "GCP_WIF_SA: $SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" echo "---------------------------------------------------"
## 配置GitHub机密
导航到GitHub存储库>设置>机密和变量>操作,并添加上面脚本输出的两个机密:
- GCP_WIF-PROVIDER
- GCP与SA
## MCP工具
服务器通过MCP协议在以下位置公开天气工具 `/mcp`.工具归还 **丰富的HTML界面** 通过 [MCP-UI](https://mcpui.dev) 在兼容的客户端中显示美丽的天气。
### `get_weather`
通过交互式UI显示按坐标获取天气。
|参数|类型|说明|
|-------------|-------|--------------------------------------|
| `latitude` |float |纬度(例如,伦敦为51.5074)|
| `longitude` |float |经度(例如,伦敦为-0.1278)|
### `get_weather_by_city`
通过交互式UI显示按城市名称获取天气(使用地理编码)。
|参数|类型|说明|
|-----------|--------|------------------------------------------|
| `city` |string |城市名称(例如,“伦敦”、“纽约”)|
### `get_weather_json`
获取原始JSON天气数据(用于编程访问)。
|参数|类型|说明|
|-------------|-------|--------------------------------------|
| `latitude` |float |纬度(例如,伦敦为51.5074)|
| `longitude` |float |经度(例如,伦敦为-0.1278)|
**UI响应包括:**
- 带有天气表情符号图标的当前温度
- 基于WMO代码的天气描述
- 湿度和风速
- 7天预报卡,包括每日高温/低温和降水量
**支持的MCP-UI主机:** ChatGPT Apps SDK、Goose、LibreChat、MCP-UI聊天、邮递员、UI检查器
## 开发流程
git clone https://github.com/ettysekhon/mcp-server-gke.git cd mcp-server-gke uv sync
uv run uvicorn src.main:app --reload --port 8000
### 端点
|端点|描述|
|-----------|--------------------------------------|
| `/` |服务状态和版本|
| `/health` |k8s探头的健康检查|
| `/mcp` |MCP服务器(流式HTTP传输)|
## 安全模型
我严格避免使用长期存在的JSON服务帐户密钥。
1. GitHub OIDC:GitHub在Action运行期间签署一个临时令牌。
1. GCP交换:谷歌根据工作负载身份池验证令牌。
1. 模拟:谷歌为github操作授予一个短期访问令牌,即服务帐户。
sequenceDiagram participant GH as GitHub Action participant GCP as Google Cloud (WIF) participant SA as Service Account
GH->>GH: 1. Sign OIDC Token GH->>GCP: 2. Exchange Token GCP->>GCP: 3. Verify Repo & Owner GCP->>SA: 4. Grant Access SA->>GH: 5. Return Short-lived Key Note over GH, SA: No static keys stored!
过程
1. 将更改提交到main。
1. 管道通过WIF进行身份验证。
1. Docker镜像被构建并推送到工件注册表(europe-west2)。
1. Kubernetes在k8s/中的清单通过新的image标签进行了水合。
1. 更改将应用于GKE集群。
- 集群名称:mcp集群
- 地区:欧洲西部2(伦敦)
- 服务类型:LoadBalancer(公开公共IP)
## 故障排除
待定外部IP部署新服务时,LoadBalancer可能需要1-3分钟来配置静态IP。通过以下方式监控流程:
kubectl get service mcp-server-service --watch
### 测试已部署的服务
一旦你有了外部IP:
Health check
curl http:///health
Service status
curl http:///
### 测试MCP工具
#### MCP检查器(JSON调试)
使用 [MCP检查员](https://github.com/modelcontextprotocol/inspector) 对于原始协议测试:
npx @modelcontextprotocol/inspector
1. 集 **传输类型** 到 `Streamable HTTP`
1. 输入URL: `http:///mcp`
1. 点击 **连接**
1. 首选 **工具** 要测试的选项卡 `get_weather` 和 `get_weather_by_city`

#### UI检查器(MCP-UI预览版)
使用 [ui检查员](https://github.com/idosal/ui-inspector) 查看渲染的HTML天气卡:
git clone https://github.com/idosal/ui-inspector cd ui-inspector npm install npm run dev
然后连接到 `http://localhost:8000/mcp` (本地)或 `http:///mcp` (已部署)。
## 路线图
- \[x\] MCP协议:集成FastMCP和Open-Meteo天气API
- \[x\] MCP-UI:通过MCP-UI服务器显示丰富的HTML天气
- \[\]身份验证:实现用于客户端安全的API密钥中间件
- \[\]数据库:配置到Cloud SQL的私有IP连接