cloudflare-mcp-dcr-bridge
by jerryscy
README.md
# Cloudflare MCP Portal DCR Bridge for Gemini Enterprise
Package repository for deploying a **Cloudflare MCP Portal Bridge** with **Dynamic Client Registration (DCR)** and **OAuth 2.0 proxying** on **Google Cloud Run**, enabling **Gemini Enterprise** (Google Cloud AI Companions / Agent Space) to connect seamlessly to **Cloudflare Zero Trust MCP Server Portals**.
---
## Architecture & Header Flow
```
┌───────────────────────────┐ OAuth 2.0 + DCR / MCP JSON-RPC ┌───────────────────────────────────┐ CF Access Service Token ┌───────────────────────────────┐
│ │ ───────────────────────────────────────────> │ cloudflare-mcp-dcr-bridge │ ────────────────────────────────────> │ Cloudflare Zero Trust │
│ Gemini Enterprise App │ Authorization: Bearer <token> │ (Google Cloud Run Service) │ CF-Access-Client-Id: <ID> │ MCP Server Portal │
│ (Data Store Remote MCP) │ Mcp-Session-Id: <session> │ │ CF-Access-Client-Secret: <SECRET> │ (https://<portal>/mcp) │
│ │ <─────────────────────────────────────────── │ │ Mcp-Session-Id: <session> │ │
└───────────────────────────┘ Streamable HTTP / SSE └───────────────────────────────────┘ <──────────────────────────────────── └───────────────────────────────┘
│
▼
┌───────────────────────────────┐
│ Upstream MCP Servers │
│ (GitHub, Jira, Custom APIs) │
└───────────────────────────────┘
```
---
## Detailed Protocol & Header Specifications
### 1. Request Headers Forwarded to Cloudflare MCP Portal
When proxying `/mcp` requests, the bridge filters out hop-by-hop headers (`Host`, `Connection`, `Transfer-Encoding`, etc.) and forwards:
- **`CF-Access-Client-Id`**: Injected from `CF_ACCESS_CLIENT_ID` env var.
- **`CF-Access-Client-Secret`**: Injected from `CF_ACCESS_CLIENT_SECRET` env var.
- **`Mcp-Session-Id`** / **`mcp-session-id`**: Forwarded if present for session continuity.
- **`Accept`**: Set to `application/json, text/event-stream` to support both JSON-RPC and SSE streaming.
- **`Content-Type`**: Defaults to `application/json`.
- **`User-Agent`** & custom `x-*` / `mcp-*` headers: Preserved.
### 2. Response Headers Returned to Gemini Enterprise
- **`Content-Type`**: Preserves original content type (e.g., `application/json` or `text/event-stream`).
- **`Mcp-Session-Id`**: Preserved and exposed for client session tracking.
- **`WWW-Authenticate`**: Preserved for 401 challenges.
- **CORS Expose-Headers**: Configured for `Mcp-Session-Id`, `mcp-version`, `CF-Access-Client-Id`, `CF-Access-Client-Secret`, `Authorization`, and `WWW-Authenticate`.
### 3. Real-Time Streaming Support
The `/mcp` proxy uses `httpx` async stream generators and FastAPI `StreamingResponse` to deliver SSE event streams and chunked JSON-RPC responses in real-time without buffering.
### 4. OAuth 2.0 & DCR Compliance
- Supports **`client_secret_post`** (JSON/form parameters) and **`client_secret_basic`** (`Authorization: Basic <base64>` header).
- Guarantees `refresh_token`, `expires_in`, and `token_type: "Bearer"` in response JSON.
- Provides `/.well-known/oauth-authorization-server` and `/.well-known/mcp-configuration` discovery metadata.
---
## Target GCP Specifications
- **GCP Project**: `{YOUR_GCP_PROJECT_ID}` (Configurable via `GCP_PROJECT_ID` env var)
- **Cloud Run Service**: `cloudflare-mcp-dcr-bridge` (Region: `us-central1`)
---
## Prerequisites
1. **Google Cloud SDK (`gcloud` CLI)** installed and authenticated:
```bash
gcloud auth login
gcloud config set project <YOUR_PROJECT_ID>
```
2. **Cloudflare Zero Trust MCP Portal** setup:
* Navigate to **Cloudflare Dashboard** -> **Zero Trust** -> **Access controls** -> **AI controls** -> **MCP Portals**.
* Copy your MCP Portal URL (e.g., `https://<portal-name>.<team-domain>.cloudflareaccess.com/mcp` or custom domain).
3. **Cloudflare Access Service Token** (for machine-to-machine authentication):
* Go to **Zero Trust** -> **Access** -> **Service Tokens**.
* Click **Add a Service Token**, name it `gemini-enterprise-mcp-bridge`, and copy the **Client ID** and **Client Secret**.
* Ensure a **Service Auth** policy is added to both the MCP Portal Access App and all downstream linked MCP servers.
---
## Environment Setup (`.env`)
Copy `.env.example` to `.env` and fill in your GCP Project ID, Cloudflare MCP Portal URL, and Cloudflare Access Service Token credentials:
```bash
cp .env.example .env
```
`.env` configuration example:
```env
# GCP Configuration
GCP_PROJECT_ID=my-gcp-project-id
GCP_REGION=us-central1
SERVICE_NAME=cloudflare-mcp-dcr-bridge
# Cloudflare MCP Portal Configuration
CLOUDFLARE_MCP_PORTAL_URL=https://my-portal.my-team.cloudflareaccess.com/mcp
# Cloudflare Access Service Token (Machine-to-Machine Auth)
CF_ACCESS_CLIENT_ID=1234567890abcdef.access
CF_ACCESS_CLIENT_SECRET=abcdef1234567890abcdef1234567890abcdef1234567890
# Optional Bridge Secret for DCR Token Validation
BRIDGE_SECRET=cloudflare-mcp-dcr-secret
```
---
## Quick Deployment Command
```bash
chmod +x deploy.sh
./deploy.sh
```
or deploy directly via `gcloud`:
```bash
gcloud builds submit --tag us-central1-docker.pkg.dev/{YOUR_GCP_PROJECT_ID}/cloud-run-source-deploy/cloudflare-mcp-dcr-bridge:latest
gcloud run deploy cloudflare-mcp-dcr-bridge \
--image us-central1-docker.pkg.dev/{YOUR_GCP_PROJECT_ID}/cloud-run-source-deploy/cloudflare-mcp-dcr-bridge:latest \
--region us-central1 \
--project {YOUR_GCP_PROJECT_ID} \
--allow-unauthenticated \
--set-env-vars "CLOUDFLARE_MCP_PORTAL_URL=https://my-portal.my-team.cloudflareaccess.com/mcp,CF_ACCESS_CLIENT_ID={CLIENT_ID},CF_ACCESS_CLIENT_SECRET={CLIENT_SECRET}"
```
---
## Endpoints Provided
| Endpoint | Method | Description |
| :--- | :--- | :--- |
| `/.well-known/oauth-authorization-server` | GET | OAuth 2.0 Authorization Server Metadata (RFC 8414) |
| `/.well-known/mcp-configuration` | GET | Remote MCP Server discovery metadata |
| `/register` | POST | Dynamic Client Registration (DCR, RFC 7591) |
| `/authorize` | GET | OAuth 2.0 Authorization Proxy for Gemini Enterprise |
| `/token` | POST | OAuth 2.0 Token Exchange for Gemini Enterprise (supports Basic & POST auth) |
| `/mcp` | POST / GET / OPTIONS | Streamable HTTP/SSE MCP Proxy (adds Cloudflare Access Headers & streams responses) |
| `/health` | GET | Service Health & Target Portal Status Check |
---
## How to Register / Generate Client ID for Gemini Enterprise
### Option A: Automatically via Gemini Enterprise DCR
When configuring the Extension / Data Store in Gemini Enterprise, enter the Registration URL (`https://{YOUR_CLOUD_RUN_SERVICE_URL}/register`). Gemini Enterprise will automatically execute `/register` and populate the Client ID and Secret fields behind the scenes!
### Option B: Via `curl` Command in Terminal (Manual)
Run this request to retrieve or generate a Client ID and Secret directly:
```bash
curl -X POST https://{YOUR_CLOUD_RUN_SERVICE_URL}/register \
-H "Content-Type: application/json" \
-d '{
"client_name": "Gemini Enterprise App",
"redirect_uris": ["https://cloudaicompanions.google.com/oauth/callback"]
}'
```
**JSON Output Example**:
```json
{
"client_id": "cf-dcr-a1b2c3d4e5f67890",
"client_secret": "cloudflare-mcp-dcr-secret-0123456789abcdef",
"client_name": "Gemini Enterprise App",
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"],
"scope": "mcp:read offline_access"
}
```
---
## Connecting to Gemini Enterprise
1. Open **Google Cloud Console** -> **Gemini Enterprise** (or **Agent Space** / **Discovery Engine**).
2. Go to **Connected data stores** -> **+ New data store** -> **Add MCP server** and enter these parameters:
| Setting Field | Value to Enter |
| :--- | :--- |
| **MCP Server URL** | `https://{YOUR_CLOUD_RUN_SERVICE_URL}/mcp` |
| **Authorization URL** | `https://{YOUR_CLOUD_RUN_SERVICE_URL}/authorize` |
| **Token URL** | `https://{YOUR_CLOUD_RUN_SERVICE_URL}/token` |
| **Registration URL (DCR)** | `https://{YOUR_CLOUD_RUN_SERVICE_URL}/register` |
| **Client ID** | `cf-dcr-...` *(or auto-generated via DCR)* |
| **Client Secret** | `cloudflare-mcp-dcr-secret-...` *(or auto-generated via DCR)* |
| **Scopes** | `offline_access` |
| **Enable PKCE Support** | **CHECK / ENABLE** ✅ |
| **Use HTTP Basic Authentication** | **UNCHECK / DISABLE** ❌ *(or ENABLE if using client_secret_basic)* |
3. After saving the Connected data store, click **Actions** and select **Reload custom actions**.
4. Gemini Enterprise can now invoke tools provided by your Cloudflare MCP Server Portal!
---
## License
MIT License.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues