Skip to content

Commit ae2dd2b

Browse files
Auth0 MCP Demo (#40)
* feat: added example api worker to be called by mcp server * chore: fix formatting issues * chore: jwt middleware formatting * feat: added mcp worker for auth0 * chore: fix formatting issues * feat: replaced generic api with a todos api * chore: minor improvements to todos api * feat: added auth0 mcp server * feat: added consent screen * chore: added docs for the playground * commit changes to root package-lock --------- Co-authored-by: Jeremy Morrell <[email protected]>
1 parent 8a71c66 commit ae2dd2b

32 files changed

+4740
-0
lines changed

demos/remote-mcp-auth0/.gitignore

+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# Logs
2+
3+
logs
4+
_.log
5+
npm-debug.log_
6+
yarn-debug.log*
7+
yarn-error.log*
8+
lerna-debug.log*
9+
.pnpm-debug.log*
10+
11+
# Diagnostic reports (https://nodejs.org/api/report.html)
12+
13+
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
14+
15+
# Runtime data
16+
17+
pids
18+
_.pid
19+
_.seed
20+
\*.pid.lock
21+
22+
# Directory for instrumented libs generated by jscoverage/JSCover
23+
24+
lib-cov
25+
26+
# Coverage directory used by tools like istanbul
27+
28+
coverage
29+
\*.lcov
30+
31+
# nyc test coverage
32+
33+
.nyc_output
34+
35+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
36+
37+
.grunt
38+
39+
# Bower dependency directory (https://bower.io/)
40+
41+
bower_components
42+
43+
# node-waf configuration
44+
45+
.lock-wscript
46+
47+
# Compiled binary addons (https://nodejs.org/api/addons.html)
48+
49+
build/Release
50+
51+
# Dependency directories
52+
53+
node_modules/
54+
jspm_packages/
55+
56+
# Snowpack dependency directory (https://snowpack.dev/)
57+
58+
web_modules/
59+
60+
# TypeScript cache
61+
62+
\*.tsbuildinfo
63+
64+
# Optional npm cache directory
65+
66+
.npm
67+
68+
# Optional eslint cache
69+
70+
.eslintcache
71+
72+
# Optional stylelint cache
73+
74+
.stylelintcache
75+
76+
# Microbundle cache
77+
78+
.rpt2_cache/
79+
.rts2_cache_cjs/
80+
.rts2_cache_es/
81+
.rts2_cache_umd/
82+
83+
# Optional REPL history
84+
85+
.node_repl_history
86+
87+
# Output of 'npm pack'
88+
89+
\*.tgz
90+
91+
# Yarn Integrity file
92+
93+
.yarn-integrity
94+
95+
# dotenv environment variable files
96+
97+
.env
98+
.env.development.local
99+
.env.test.local
100+
.env.production.local
101+
.env.local
102+
103+
# parcel-bundler cache (https://parceljs.org/)
104+
105+
.cache
106+
.parcel-cache
107+
108+
# Next.js build output
109+
110+
.next
111+
out
112+
113+
# Nuxt.js build / generate output
114+
115+
.nuxt
116+
dist
117+
118+
# Gatsby files
119+
120+
.cache/
121+
122+
# Comment in the public line in if your project uses Gatsby and not Next.js
123+
124+
# https://nextjs.org/blog/next-9-1#public-directory-support
125+
126+
# public
127+
128+
# vuepress build output
129+
130+
.vuepress/dist
131+
132+
# vuepress v2.x temp and cache directory
133+
134+
.temp
135+
.cache
136+
137+
# Docusaurus cache and generated files
138+
139+
.docusaurus
140+
141+
# Serverless directories
142+
143+
.serverless/
144+
145+
# FuseBox cache
146+
147+
.fusebox/
148+
149+
# DynamoDB Local files
150+
151+
.dynamodb/
152+
153+
# TernJS port file
154+
155+
.tern-port
156+
157+
# Stores VSCode versions used for testing VSCode extensions
158+
159+
.vscode-test
160+
161+
# yarn v2
162+
163+
.yarn/cache
164+
.yarn/unplugged
165+
.yarn/build-state.yml
166+
.yarn/install-state.gz
167+
.pnp.\*
168+
169+
# wrangler project
170+
171+
.dev.vars
172+
.wrangler/

demos/remote-mcp-auth0/.npmrc

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
shamefully-hoist=true
2+
use-workspace-protocol=true
3+
link-workspace-packages = true
4+
prefer-workspace-packages = true

demos/remote-mcp-auth0/.prettierrc

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"printWidth": 140,
3+
"singleQuote": true,
4+
"semi": false,
5+
"useTabs": false,
6+
"overrides": [
7+
{
8+
"files": ["*.jsonc"],
9+
"options": {
10+
"trailingComma": "none"
11+
}
12+
}
13+
]
14+
}

demos/remote-mcp-auth0/README.md

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Model Context Protocol (MCP) Server + Auth0
2+
3+
This is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) server that supports remote MCP connections, with Auth0 built-in.
4+
5+
The MCP server (powered by [Cloudflare Workers](https://developers.cloudflare.com/workers/)):
6+
7+
- Acts as OAuth _Server_ to your MCP clients
8+
- Acts as OIDC _Client_ to your Auth0 Tenant
9+
10+
## Getting Started
11+
12+
This demo allows an MCP Server to call a protected API on behalf of the authenticated user. To get started you will need the following:
13+
14+
1. Deploy the [Todos API](./packages/todos-api/README.md)
15+
2. Run the [MCP Server](./packages/mcp-auth0-oidc/README.md)
16+
17+
## Access the remote MCP server from the Cloudflare Workers AI LLM Playground
18+
19+
Navigate to [https://playground.ai.cloudflare.com/](https://playground.ai.cloudflare.com/) and connect to your MCP server on the bottom left using the following URL pattern:
20+
21+
```bash
22+
https://mcp-auth0-oidc.<your-subdomain>.workers.dev/sse
23+
```
24+
25+
This will open a popup where you can sign in after which you'll be able to use all of the tools.
26+
27+
<img src="./docs/playground.jpg" width="500" alt="Workers AI LLM Playground">
28+
29+
## Access the remote MCP server from Claude Desktop
30+
31+
Open Claude Desktop and navigate to Settings -> Developer -> Edit Config. This opens the configuration file that controls which MCP servers Claude can access.
32+
33+
Replace the content with the following configuration. Once you restart Claude Desktop, a browser window will open showing your OAuth login page. Complete the authentication flow to grant Claude access to your MCP server. After you grant access, the tools will become available for you to use.
34+
35+
```
36+
{
37+
"mcpServers": {
38+
"math": {
39+
"command": "npx",
40+
"args": [
41+
"mcp-remote",
42+
"https://mcp-auth0-oidc.<your-subdomain>.workers.dev/sse"
43+
]
44+
}
45+
}
46+
}
47+
```
48+
49+
Once the Tools (under 🔨) show up in the interface, you can ask Claude to use them. For example: "Could you list my todos". Claude should invoke the tool and show the result generated by the MCP server.
50+
51+
<img src="./docs/claude.png" width="500" alt="Claude Desktop">
589 KB
Loading
175 KB
Loading
85.7 KB
Loading
Loading
Loading

demos/remote-mcp-auth0/docs/local.jpg

116 KB
Loading
93.3 KB
Loading
264 KB
Loading

demos/remote-mcp-auth0/package.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "mcp-auth0",
3+
"version": "0.0.1",
4+
"private": true,
5+
"scripts": {
6+
"deploy": "wrangler deploy",
7+
"dev": "wrangler dev",
8+
"start": "wrangler dev",
9+
"cf-typegen": "wrangler types"
10+
},
11+
"devDependencies": {
12+
"prettier": "^3.5.3",
13+
"typescript": "^5.5.2",
14+
"wrangler": "^4.3.0"
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Model Context Protocol (MCP) Server
2+
3+
This is a MCP server which will require the user to first authenticate. The MCP server will then be able to call protected APIs on behalf of the user.
4+
5+
## Configuration
6+
7+
### Todos API
8+
9+
Before you can use the MCP server, you will need to deploy the Todos API as documented [here](../todos-api/README.md).
10+
11+
### Auth0 Configuration
12+
13+
In the Auth0 dashboard, create a new application in the Applications section (type: "Regular Web Application").
14+
15+
<img src="../../docs/create-application.jpg" width="500" alt="Create Application">
16+
17+
Once the application is created, configure the following URL as the callback URL when developing locally:
18+
19+
```
20+
http://localhost:8788/callback
21+
```
22+
23+
### Set up a KV namespace
24+
25+
- Create the KV namespace:
26+
`wrangler kv:namespace create "OAUTH_KV"`
27+
- Update the Wrangler file with the KV ID
28+
29+
## Development
30+
31+
Create a `.dev.vars` file in the root of the project with the following structure:
32+
33+
```
34+
AUTH0_DOMAIN=Your Auth0 domain (eg: acme.auth0.com)
35+
AUTH0_CLIENT_ID=The Client ID of the application you created in Auth0
36+
AUTH0_CLIENT_SECRET=The Client Secret of the application you created in Auth0
37+
AUTH0_AUDIENCE=urn:todos-api
38+
AUTH0_SCOPE=openid email profile offline_access read:todos
39+
NODE_ENV=development
40+
API_BASE_URL=The base URL of the Todos API (eg: https://todos-api.sandrino.run)
41+
```
42+
43+
The `AUTH0_DOMAIN` is the domain of the Auth0 tenant. The `AUTH0_AUDIENCE` is the audience of the API you created in the Auth0 tenant (eg: `urn:todos-api`).
44+
45+
### Testing the MCP Server
46+
47+
To start the MCP server, you can use the following command:
48+
49+
```
50+
pnpm run dev
51+
```
52+
53+
With MCP Inspector you can connect to the MCP server, list the available tools and call them. Make sure to set the transport type to `sse` and the URL to `http://localhost:8788`.
54+
55+
<img src="../../docs/local.jpg" width="500" alt="MCP Inspector">
56+
57+
## Deploying the MCP Server to Cloudflare
58+
59+
To deploy the MCP Server to Cloudflare, you will first need to set the following secrets:
60+
61+
```bash
62+
wrangler secret put AUTH0_DOMAIN
63+
wrangler secret put AUTH0_CLIENT_ID
64+
wrangler secret put AUTH0_CLIENT_SECRET
65+
wrangler secret put AUTH0_AUDIENCE
66+
wrangler secret put AUTH0_SCOPE
67+
wrangler secret put API_BASE_URL
68+
```
69+
70+
Once the secrets are set, you can deploy the API with the following command:
71+
72+
```bash
73+
pnpm run deploy
74+
```
75+
76+
In the Auth0 dashboard, also make sure to add a new Callback URL for your deployed MCP server, eg:
77+
78+
```bash
79+
https://mcp-auth0-oidc.<your-subdomain>.workers.dev/callback
80+
```
81+
82+
To test this you can now use the Workers AI LLM Playground. Navigate to [https://playground.ai.cloudflare.com/](https://playground.ai.cloudflare.com/) and connect to your MCP server on the bottom left using the following URL pattern:
83+
84+
```bash
85+
https://mcp-auth0-oidc.<your-subdomain>.workers.dev/sse
86+
```
87+
88+
This will open a popup where you can sign in after which you'll be able to use all of the tools.
89+
90+
<img src="../../docs/playground.jpg" width="500" alt="Workers AI LLM Playground">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "mcp-auth0-oidc",
3+
"version": "0.0.1",
4+
"private": true,
5+
"scripts": {
6+
"deploy": "wrangler deploy",
7+
"dev": "wrangler dev",
8+
"start": "wrangler dev",
9+
"cf-typegen": "wrangler types"
10+
},
11+
"devDependencies": {
12+
"@cloudflare/workers-oauth-provider": "^0.0.2",
13+
"@cloudflare/workers-types": "^4.20250310.0",
14+
"@modelcontextprotocol/sdk": "^1.7.0",
15+
"hono": "^4.7.4",
16+
"jose": "^6.0.10",
17+
"just-pick": "^4.2.0",
18+
"oauth4webapi": "^3.3.1",
19+
"workers-mcp": "0.1.0-3",
20+
"zod": "^3.24.2"
21+
}
22+
}

0 commit comments

Comments
 (0)