Skip to content

Commit f2bfc16

Browse files
Document transformation flow with diagrams
1 parent 7aa5faf commit f2bfc16

File tree

3 files changed

+73
-7
lines changed

3 files changed

+73
-7
lines changed

OPERATIONS.md

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,26 @@ no additional environment variables are necessary for the binding itself.
4242

4343
## 3. Migration Phases
4444

45+
```mermaid
46+
sequenceDiagram
47+
participant Eng as Engineering
48+
participant Access as Cloudflare Access
49+
participant Gateway as AI Gateway
50+
participant Worker as MCP Worker
51+
participant Apps as Internal Apps
52+
53+
Eng->>Access: Create SaaS app + policies
54+
Access-->>Eng: SaaS app ID
55+
Eng->>Apps: Add linked_app_token rule<br/>with SaaS app ID
56+
Eng->>Gateway: Provision m365-egress-gateway<br/>+ dynamic route(s)
57+
Eng->>Worker: Update wrangler.toml<br/>+ secrets + env types
58+
Worker->>Gateway: env.AI.run(...) with metadata
59+
Worker->>Access: Present OAuth token (SSO)
60+
Worker->>Apps: Call with Access token (optional)
61+
Access-->>Worker: Permit/deny based on policies
62+
Gateway-->>Worker: Enforce egress controls<br/>(logs, DLP, rate limits)
63+
```
64+
4565
### Phase 1 – Establish the Security Perimeter
4666

4767
1. Create a **Cloudflare Access** self-hosted application for `mcp.<domain>`.
@@ -50,24 +70,33 @@ no additional environment variables are necessary for the binding itself.
5070
- Service token policy for automation/CI use cases
5171
3. Validate by browsing to the Worker route; ensure Access blocks unauthenticated traffic.
5272

53-
### Phase 2 – Deploy AI Gateway Control Plane
73+
### Phase 2 – Register the MCP Portal & Linked Apps
74+
75+
1. Add the Worker as an Access for SaaS application (OIDC) following the [Secure MCP servers guide](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/mcp-servers/saas-mcp/).
76+
2. Record the SaaS application `id` (API: `GET /client/v4/accounts/:id/access/apps`).
77+
3. For each internal HTTP service the MCP server should call, create or update the Access policy to include a `linked_app_token` rule referencing the SaaS app `id` ([docs](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/mcp-servers/linked-apps/)).
78+
4. Update the self-hosted app configuration to require the new policy so tokens issued to the MCP portal are accepted.
79+
5. Expose the MCP portal via **Access → AI Controls → MCP Portals** and associate it with the SaaS app and Access policies.
80+
81+
### Phase 3 – Deploy AI Gateway Control Plane
5482

5583
1. Create an AI Gateway (e.g., `m365-egress-gateway`).
5684
2. Enable logging, caching, rate limiting, and DLP policies as required.
57-
3. Define dynamic routes:
85+
3. Define dynamic routes ([docs](https://developers.cloudflare.com/ai-gateway/features/dynamic-routing/)):
5886
- `dynamic/microsoft-graph-handler` – proxies Microsoft Graph requests
5987
- Additional routes for LLM/tooling integrations (optional)
6088
4. (Optional) Issue a gateway service token for worker authentication.
6189

62-
### Phase 3 – Refactor the Worker
90+
### Phase 4 – Refactor the Worker
6391

6492
1. Update `wrangler.toml`
6593
- Remove `[vars]` blocks; rely on secrets only
6694
- Add `[[ai]] binding = "AI"
6795
- Confirm Durable Object binding (`MCP_OBJECT`) and routes
6896
2. Extend the TypeScript `Env` interface with `AI: Ai`, Access headers (`CF_Access_User`, etc.),
6997
and required secrets.
70-
3. Replace all `fetch` calls to Microsoft Graph with `env.AI.run(...)`:
98+
3. Replace all `fetch` calls to Microsoft Graph with `env.AI.run(...)`
99+
([binding reference](https://developers.cloudflare.com/ai-gateway/integrations/worker-binding-methods/)):
71100

72101
```ts
73102
await env.AI.run(
@@ -92,15 +121,16 @@ no additional environment variables are necessary for the binding itself.
92121

93122
4. Centralise error handling around `env.AI.run` responses to translate gateway errors
94123
into MCP-friendly responses.
95-
5. Ensure tokens and secrets are always sourced from `env`, not imported constants.
124+
5. Optionally capture `env.AI.aiGatewayLogId` for correlation with gateway telemetry.
125+
6. Ensure tokens and secrets are always sourced from `env`, not imported constants.
96126

97-
### Phase 4 – Deploy
127+
### Phase 5 – Deploy
98128

99129
1. `npm install && npm run validate`
100130
2. `wrangler deploy --env production`
101131
3. Confirm Access headers reach the worker if you intend to log authenticated identities.
102132

103-
### Phase 5 – Validation Checklist
133+
### Phase 6 – Validation Checklist
104134

105135
- [ ] Access prompt enforced (SSO + MFA + device posture)
106136
- [ ] OAuth 2.1 flow completes; Microsoft consent screen appears

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,25 @@ clear ingress controls, governed egress, and auditable operations.
5353
5. **Deploy & Validate** – run `wrangler deploy --env production`, complete the Access SSO,
5454
Microsoft consent, and tool execution flow; confirm AI Gateway/Access telemetry.
5555

56+
### Transformation at a Glance
57+
58+
```mermaid
59+
flowchart LR
60+
A[Early MCP Worker<br>Direct fetch + inline secrets] --> B[Phase 1<br>Cloudflare Access App]
61+
B --> C[Phase 2<br>MCP Portal + Linked Apps]
62+
C --> D[Phase 3<br>AI Gateway Dynamic Routes]
63+
D --> E[Phase 4<br>Code Refactor<br>env.AI.run + metadata]
64+
E --> F[Phase 5<br>Deploy & Validate<br>Access SSO • Gateway logs]
65+
```
66+
67+
## Reference Material
68+
69+
- Cloudflare docs – [AI Gateway binding methods](https://developers.cloudflare.com/ai-gateway/integrations/worker-binding-methods/)
70+
- Cloudflare docs – [Universal endpoint](https://developers.cloudflare.com/ai-gateway/usage/universal/)
71+
- Cloudflare docs – [Dynamic routing](https://developers.cloudflare.com/ai-gateway/features/dynamic-routing/)
72+
- Cloudflare docs – [Access linked apps for MCP servers](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/mcp-servers/linked-apps/)
73+
- Cloudflare GitHub – [AI Gateway MCP server](https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/ai-gateway) (log tooling & OAuth patterns)
74+
5675
## Contributing
5776

5877
All feature work, tool enhancements, or general documentation improvements should originate in

TECHNICAL.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,17 @@ Client (MCP) → Cloudflare Access → Worker (/sse) → Durable Object
1616
Microsoft Graph / External APIs
1717
```
1818

19+
```mermaid
20+
stateDiagram-v2
21+
[*] --> Access
22+
Access --> Worker : SSO / JWT
23+
Worker --> DurableObject : MCP Session
24+
Worker --> Gateway : env.AI.run()
25+
Gateway --> Graph : Dynamic Route
26+
Gateway --> Worker : Response + Log ID
27+
Worker --> [*] : Tool result to MCP client
28+
```
29+
1930
1. **Cloudflare Access** acts as checkpoint #1 (perimeter). Requests without a valid Access token never
2031
reach the Worker. Identity, device posture, and service token claims can be surfaced through headers
2132
(`CF-Access-Authenticated-User-Email`, `CF-Access-Jwt-Assertion`).
@@ -93,11 +104,16 @@ const response = await env.AI.run(
93104
- **`path`**: Relative to Microsoft Graph base URL, allowing the gateway to centralise origin logic.
94105
- **Metadata**: Supply user identifier, MCP tool name, and correlation IDs so that gateway logs
95106
support incident response and analytics.
107+
- **Gateway helpers**: Capture `env.AI.aiGatewayLogId` for the most recent call or invoke
108+
`env.AI.gateway("m365-egress-gateway").patchLog(...)` / `getLog(...)` when you need to append
109+
metadata or fetch request bodies ([binding methods](https://developers.cloudflare.com/ai-gateway/integrations/worker-binding-methods/)).
96110
- **Error Handling**: The worker should translate non-2xx responses into structured MCP errors,
97111
indicating whether the issue is policy (429/DLP) vs Graph-specific (403/401).
98112

99113
## 4. Access Awareness
100114

115+
Cloudflare Access for SaaS issues the OAuth token that the worker presents on each request. If the worker later needs to call internal HTTP applications, configure `linked_app_token` policies so the same token is honoured downstream ([docs](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/mcp-servers/linked-apps/)).
116+
101117
The worker can read Access-derived headers to enrich logs or enforce additional checks, for example:
102118

103119
```ts
@@ -119,6 +135,7 @@ This data can be injected into the AI Gateway metadata payload for end-to-end tr
119135
## 6. Logging & Observability
120136

121137
- **AI Gateway**: Primary location for monitoring outbound traffic, rate limiting, and DLP violations.
138+
- Dynamic routes expose provider/model decisions and quotas ([docs](https://developers.cloudflare.com/ai-gateway/features/dynamic-routing/)).
122139
- **Workers Tail**: Use `wrangler tail --metadata` to surface request IDs and Access identity info.
123140
- **Access Audit Logs**: Provide authentication history, device posture evaluation, and policy results.
124141
- **Microsoft Entra ID**: Audit application sign-ins to confirm OAuth flows remain compliant.

0 commit comments

Comments
 (0)