Skip to content

Commit 0ba4637

Browse files
authored
Merge pull request #498 from GreenStage/egomes/remote-mcp-cf-access-self-hosted
2 parents 9b0d887 + 58d517f commit 0ba4637

10 files changed

Lines changed: 18809 additions & 0 deletions

File tree

demos.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@
107107
},
108108
"./demos/hello-world": {
109109
"package_json_hash": "286f536168d5b046228c88c689758c9eb4ff3fb8"
110+
},
111+
"./demos/remote-mcp-cf-access-self-hosted": {
112+
"package_json_hash": "711087c91bcd285999ba2bba9db991df68220718"
110113
}
111114
}
112115
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules/
2+
.wrangler/
3+
.dev.vars
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# MCP Server + Access Self-Hosted App
2+
3+
A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) server protected by Cloudflare Access as a self-hosted application. Unlike the [Access for SaaS demo](../remote-mcp-cf-access/), this approach requires **no OAuth implementation** — Cloudflare Access handles authentication automatically.
4+
5+
The MCP server demonstrates:
6+
7+
- Validating the Access JWT signature against your team's public keys using [`jose`](https://www.npmjs.com/package/jose)
8+
- Verifying the JWT issuer and audience claims
9+
- Reading user identity from the validated JWT
10+
- Conditionally exposing tools based on user identity
11+
12+
## Getting Started
13+
14+
Clone the repo and install dependencies:
15+
16+
```bash
17+
npm install
18+
```
19+
20+
### Create a self-hosted Access application
21+
22+
1. In [Cloudflare One](https://one.dash.cloudflare.com), go to **Access controls** > **Applications** > **Add an application** > **Self-hosted**.
23+
2. Set the **Application domain** to your Worker URL (e.g., `mcp-access-self-hosted.<your-subdomain>.workers.dev`).
24+
3. Add an Access policy to control who can connect (e.g., allow emails ending in `@yourcompany.com`).
25+
26+
### Configure environment variables
27+
28+
Update `wrangler.jsonc` with your Access application details:
29+
30+
- `TEAM_DOMAIN`: Your Cloudflare One team domain (e.g., `https://<your-team-name>.cloudflareaccess.com`)
31+
- `POLICY_AUD`: Your application's [AUD tag](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/validating-json/#get-your-aud-tag) (found under **Access controls** > **Applications** > your app > **Basic information**)
32+
33+
### Deploy
34+
35+
```bash
36+
wrangler deploy
37+
```
38+
39+
### Test
40+
41+
Test the remote server using [Inspector](https://modelcontextprotocol.io/docs/tools/inspector):
42+
43+
```bash
44+
npx @modelcontextprotocol/inspector@latest
45+
```
46+
47+
Enter `https://mcp-access-self-hosted.<your-subdomain>.workers.dev/mcp` and connect. You will be prompted to log in through your Access identity provider.
48+
49+
### Connect from Claude Desktop
50+
51+
Open Claude Desktop, go to Settings > Developer > Edit Config, and add:
52+
53+
```json
54+
{
55+
"mcpServers": {
56+
"access-self-hosted": {
57+
"type": "http",
58+
"url": "https://mcp-access-self-hosted.<your-subdomain>.workers.dev/mcp"
59+
}
60+
}
61+
}
62+
```
63+
64+
### Local Development
65+
66+
```bash
67+
wrangler dev
68+
```
69+
70+
Note: In local development, `Cf-Access-Jwt-Assertion` is not set by Access. You can test by manually setting the header or by using `cloudflared access` to tunnel through Access.

0 commit comments

Comments
 (0)