Skip to content

Commit d82ddf7

Browse files
authored
Merge pull request #143 from openai/ecommerce-app-for-sa-bootcamp
Add mixed auth example app
2 parents 1243be8 + 6e1df15 commit d82ddf7

File tree

10 files changed

+895
-2
lines changed

10 files changed

+895
-2
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ The MCP servers in this demo highlight how each tool can light up widgets by com
3939
- `solar-system_server_python/` – Python MCP server for the 3D solar system widget.
4040
- `kitchen_sink_server_node/` – Node MCP server for the kitchen-sink-lite widget.
4141
- `kitchen_sink_server_python/` – Python MCP server for the kitchen-sink-lite widget.
42+
- `authenticated_server_python/` – Python MCP server that demonstrates authenticated tool calls.
4243
- `build-all.mts` – Vite build orchestrator that produces hashed bundles for every widget entrypoint.
4344

4445
### Kitchen sink lite overview
@@ -104,8 +105,11 @@ The repository ships several demo MCP servers that highlight different widget bu
104105

105106
- **Pizzaz (Node & Python)** – pizza-inspired collection of tools and components
106107
- **Solar system (Python)** – 3D solar system viewer
108+
<<<<<<< HEAD
109+
- # **Authenticated (Python)** – set of tools that require different levels of OAuth
107110
- **Kitchen sink lite (Node & Python)** – minimal widget + server pairing that demonstrates tool output, widget state, `callTool`, and host helpers
108111
- **Shopping cart (Python)** – simple shopping cart widget that demonstrates how to use `widgetSessionId` to keep state between tool calls
112+
> > > > > > > 1243be83efb820fcc288f7359bb67446e14b74ec
109113
110114
### Pizzaz Node server
111115

@@ -123,6 +127,15 @@ pip install -r pizzaz_server_python/requirements.txt
123127
uvicorn pizzaz_server_python.main:app --port 8000
124128
```
125129

130+
### Authenticated Python server
131+
132+
```bash
133+
python -m venv .venv
134+
source .venv/bin/activate
135+
pip install -r authenticated_server_python/requirements.txt
136+
uvicorn authenticated_python_server.main:app --port 8000
137+
```
138+
126139
### Solar system Python server
127140

128141
```bash
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
AUTHORIZATION_SERVER_URL=https://your-domain.example.com
2+
RESOURCE_SERVER_URL=https://your-mcp-server.app/mcp
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Authenticated MCP server (Python)
2+
3+
This example shows how to build an authenticated app with the OpenAI Apps SDK.
4+
It demonstrates triggering the ChatGPT authentication UI by responding with MCP
5+
authorization metadata and follows the same OAuth flow described in the [MCP
6+
authorization spec](https://modelcontextprotocol.io/docs/tutorials/security/authorization#the-authorization-flow:-step-by-step).
7+
8+
The Apps SDK [auth guide](https://developers.openai.com/apps-sdk/build/auth#triggering-authentication-ui) covers how the UI is triggered.
9+
10+
The server exposes two tools:
11+
12+
1. `search_pizza_sf` (mixed auth, returns the `mixed-auth-search` widget)
13+
2. `see_past_orders` (OAuth required, returns the `mixed-auth-past-orders` widget with past orders data)
14+
15+
If a request is missing a token for the protected tool, the server returns an `mcp/www_authenticate` hint (backed by `WWW-Authenticate`) plus `/.well-known/oauth-protected-resource` metadata so ChatGPT knows which authorization server to use. With a valid token, the tools return widget markup or structured results.
16+
17+
## Set up
18+
19+
### 1. Configure the authorization server (Auth0)
20+
21+
> This example uses an Auth0 tenant as a default authorization server. To set up your own, follow the instructions below:
22+
23+
1. **Create an API**
24+
25+
- Auth0 Dashboard → _Applications__APIs__Create API_
26+
- Name it (e.g., `mcp-python-server`)
27+
- Identifier → `https://your-domain.example.com/mcp` (add this to your `JWT_AUDIENCES` environment variable)
28+
- (JWT) Profile → Auth0
29+
30+
2. **Enable a default audience for your tenant** (per [this community post](https://community.auth0.com/t/rfc-8707-implementation-audience-vs-resource/188990/4)) so that Auth0 issues an unencrypted RS256 JWT.
31+
32+
- Tenant settings > Default Audience > Add the API identifier you created in step 1.
33+
34+
3. **Enable Dynamic Client Registration**
35+
36+
- Go to Dashboard > Settings > Advanced and enable the [OIDC Dynamic Application Registration](https://auth0.com/docs/get-started/applications/dynamic-client-registration?tenant=openai-mcpkit-trial%40prod-us-5&locale=en-us).
37+
38+
4. **Add a social connection to the tenant** for example Google oauth2 to provide a social login mechanism for uers.
39+
- Authentication > Social > google-oauth2 > Advanced > Promote Connection to Domain Level
40+
41+
### 2. Set the environment variables
42+
43+
Create `authenticated_server_python/.env` with the values below:
44+
45+
```env
46+
AUTHORIZATION_SERVER_URL=https://your-domain.example.com
47+
RESOURCE_SERVER_URL=https://your-domain.example.com/mcp
48+
```
49+
50+
- `AUTHORIZATION_SERVER_URL`: Base URL for your OAuth authorization server (Auth0 tenant). This is what ChatGPT uses to start the OAuth flow.
51+
- `RESOURCE_SERVER_URL`: Public URL to this MCP server's `/mcp` endpoint. This is the protected resource URL advertised in the OAuth metadata.
52+
53+
### 3. Customize the app
54+
55+
Adjust the `WWW-Authenticate` construction or scopes to match your security model.
56+
57+
## Run the app
58+
59+
### Serve the static assets
60+
61+
In a separate terminal, from the root of the directory, build and serve the widget assets (required for the UI):
62+
63+
```bash
64+
pnpm run build
65+
pnpm run serve
66+
```
67+
68+
### Install python requirements
69+
70+
```bash
71+
cd authenticated_server_python/
72+
python -m venv .venv
73+
source .venv/bin/activate
74+
pip install -r requirements.txt
75+
```
76+
77+
### Run the MCP server
78+
79+
Run the following command to start the MCP server:
80+
81+
```bash
82+
uvicorn authenticated_server_python.main:app --port 8000
83+
```
84+
85+
### Tunnel with ngrok
86+
87+
In a separate tab, to expose the server publicly (required for ChatGPT to reach it), tunnel the local port with ngrok:
88+
89+
```bash
90+
ngrok http 8000
91+
```
92+
93+
Copy the `https://...ngrok-free.app` URL and set `RESOURCE_SERVER_URL` in `.env` to `https://...ngrok-free.app/mcp`
94+
95+
The server listens on `http://127.0.0.1:8000` and exposes the standard MCP endpoint at `GET /mcp`.
96+
97+
The `search_pizza_sf` tool echoes the optional `searchTerm` argument as a topping and returns structured content plus widget markup. Unauthenticated calls return the MCP auth hint so the Apps SDK can start the OAuth flow.
98+
99+
The `see_past_orders` tool requires OAuth and returns the `mixed-auth-past-orders` widget with past orders data.

0 commit comments

Comments
 (0)