Skip to main content
Glama
jerryscy

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.