|
1 | | -# Simple MCP Server with GitHub OAuth Authentication |
| 1 | +# MCP OAuth Authentication Demo |
2 | 2 |
|
3 | | -This is a simple example of an MCP server with GitHub OAuth authentication. It demonstrates the essential components needed for OAuth integration with just a single tool. |
| 3 | +This example demonstrates OAuth 2.0 authentication with the Model Context Protocol using **separate Authorization Server (AS) and Resource Server (RS)** to comply with the new RFC 9728 specification. |
4 | 4 |
|
5 | | -This is just an example of a server that uses auth, an official GitHub mcp server is [here](https://github.com/github/github-mcp-server) |
| 5 | +--- |
6 | 6 |
|
7 | | -## Overview |
| 7 | +## Setup Requirements |
8 | 8 |
|
9 | | -This simple demo to show to set up a server with: |
10 | | -- GitHub OAuth2 authorization flow |
11 | | -- Single tool: `get_user_profile` to retrieve GitHub user information |
12 | | - |
13 | | - |
14 | | -## Prerequisites |
15 | | - |
16 | | -1. Create a GitHub OAuth App: |
17 | | - - Go to GitHub Settings > Developer settings > OAuth Apps > New OAuth App |
18 | | - - Application name: Any name (e.g., "Simple MCP Auth Demo") |
19 | | - - Homepage URL: `http://localhost:8000` |
20 | | - - Authorization callback URL: `http://localhost:8000/github/callback` |
21 | | - - Click "Register application" |
22 | | - - Note down your Client ID and Client Secret |
23 | | - |
24 | | -## Required Environment Variables |
25 | | - |
26 | | -You MUST set these environment variables before running the server: |
| 9 | +**Create a GitHub OAuth App:** |
| 10 | +- Go to GitHub Settings > Developer settings > OAuth Apps > New OAuth App |
| 11 | +- **Authorization callback URL:** `http://localhost:9000/github/callback` |
| 12 | +- Note down your **Client ID** and **Client Secret** |
27 | 13 |
|
| 14 | +**Set environment variables:** |
28 | 15 | ```bash |
29 | | -export MCP_GITHUB_GITHUB_CLIENT_ID="your_client_id_here" |
30 | | -export MCP_GITHUB_GITHUB_CLIENT_SECRET="your_client_secret_here" |
| 16 | +export MCP_GITHUB_CLIENT_ID="your_client_id_here" |
| 17 | +export MCP_GITHUB_CLIENT_SECRET="your_client_secret_here" |
31 | 18 | ``` |
32 | 19 |
|
33 | | -The server will not start without these environment variables properly set. |
| 20 | +--- |
34 | 21 |
|
| 22 | +## Running the Servers |
35 | 23 |
|
36 | | -## Running the Server |
| 24 | +### Step 1: Start Authorization Server |
37 | 25 |
|
38 | 26 | ```bash |
39 | | -# Set environment variables first (see above) |
| 27 | +# Navigate to the simple-auth directory |
| 28 | +cd /Users/inna/code/mcp/python-sdk/examples/servers/simple-auth |
40 | 29 |
|
41 | | -# Run the server |
42 | | -uv run mcp-simple-auth |
| 30 | +# Start Authorization Server on port 9000 |
| 31 | +python -m mcp_simple_auth.auth_server --port=9000 |
43 | 32 | ``` |
44 | 33 |
|
45 | | -The server will start on `http://localhost:8000`. |
| 34 | +**What it provides:** |
| 35 | +- OAuth 2.0 flows (registration, authorization, token exchange) |
| 36 | +- GitHub OAuth integration for user authentication |
| 37 | +- Token introspection endpoint for Resource Servers (`/introspect`) |
| 38 | +- User data proxy endpoint (`/github/user`) |
46 | 39 |
|
47 | | -### Transport Options |
| 40 | +--- |
48 | 41 |
|
49 | | -This server supports multiple transport protocols that can run on the same port: |
| 42 | +### Step 2: Start Resource Server (MCP Server) |
50 | 43 |
|
51 | | -#### SSE (Server-Sent Events) - Default |
52 | 44 | ```bash |
53 | | -uv run mcp-simple-auth |
54 | | -# or explicitly: |
55 | | -uv run mcp-simple-auth --transport sse |
| 45 | +# In another terminal, navigate to the simple-auth directory |
| 46 | +cd /Users/inna/code/mcp/python-sdk/examples/servers/simple-auth |
| 47 | + |
| 48 | +# Start Resource Server on port 8001, connected to Authorization Server |
| 49 | +python -m mcp_simple_auth.server --port=8001 --auth-server=http://localhost:9000 --transport=streamable-http |
56 | 50 | ``` |
57 | 51 |
|
58 | | -SSE transport provides endpoint: |
59 | | -- `/sse` |
60 | 52 |
|
61 | | -#### Streamable HTTP |
| 53 | +### Step 3: Test with Client |
| 54 | + |
62 | 55 | ```bash |
63 | | -uv run mcp-simple-auth --transport streamable-http |
| 56 | +# Start Resource Server with streamable HTTP |
| 57 | +python -m mcp_simple_auth.server --port=8001 --auth-server=http://localhost:9000 --transport=streamable-http |
| 58 | + |
| 59 | +# Start client with streamable HTTP |
| 60 | +MCP_SERVER_PORT=8001 MCP_TRANSPORT_TYPE=streamable_http python -m mcp_simple_auth_client.main |
64 | 61 | ``` |
65 | 62 |
|
66 | | -Streamable HTTP transport provides endpoint: |
67 | | -- `/mcp` |
68 | 63 |
|
| 64 | +## How It Works |
69 | 65 |
|
70 | | -This ensures backward compatibility without needing multiple server instances. When using SSE transport (`--transport sse`), only the `/sse` endpoint is available. |
| 66 | +### RFC 9728 Discovery |
71 | 67 |
|
72 | | -## Available Tool |
| 68 | +**Client → Resource Server:** |
| 69 | +```bash |
| 70 | +curl http://localhost:8001/.well-known/oauth-protected-resource |
| 71 | +``` |
| 72 | +```json |
| 73 | +{ |
| 74 | + "resource": "http://localhost:8001", |
| 75 | + "authorization_servers": ["http://localhost:9000"] |
| 76 | +} |
| 77 | +``` |
73 | 78 |
|
74 | | -### get_user_profile |
| 79 | +**Client → Authorization Server:** |
| 80 | +```bash |
| 81 | +curl http://localhost:9000/.well-known/oauth-authorization-server |
| 82 | +``` |
| 83 | +```json |
| 84 | +{ |
| 85 | + "issuer": "http://localhost:9000", |
| 86 | + "authorization_endpoint": "http://localhost:9000/authorize", |
| 87 | + "token_endpoint": "http://localhost:9000/token" |
| 88 | +} |
| 89 | +``` |
75 | 90 |
|
76 | | -The only tool in this simple example. Returns the authenticated user's GitHub profile information. |
| 91 | +## Manual Testing |
77 | 92 |
|
78 | | -**Required scope**: `user` |
| 93 | +### Test Discovery |
| 94 | +```bash |
| 95 | +# Test Resource Server discovery endpoint |
| 96 | +curl -v http://localhost:8001/.well-known/oauth-protected-resource |
79 | 97 |
|
80 | | -**Returns**: GitHub user profile data including username, email, bio, etc. |
| 98 | +# Test Authorization Server metadata |
| 99 | +curl -v http://localhost:9000/.well-known/oauth-authorization-server |
| 100 | +``` |
81 | 101 |
|
| 102 | +### Test Token Introspection |
| 103 | +```bash |
| 104 | +# After getting a token through OAuth flow: |
| 105 | +curl -X POST http://localhost:9000/introspect \ |
| 106 | + -H "Content-Type: application/x-www-form-urlencoded" \ |
| 107 | + -d "token=your_access_token" |
| 108 | +``` |
82 | 109 |
|
83 | 110 | ## Troubleshooting |
84 | 111 |
|
85 | | -If the server fails to start, check: |
86 | | -1. Environment variables `MCP_GITHUB_GITHUB_CLIENT_ID` and `MCP_GITHUB_GITHUB_CLIENT_SECRET` are set |
87 | | -2. The GitHub OAuth app callback URL matches `http://localhost:8000/github/callback` |
88 | | -3. No other service is using port 8000 |
89 | | -4. The transport specified is valid (`sse` or `streamable-http`) |
| 112 | +| **Issue** | **Solution** | |
| 113 | +|-----------|-------------| |
| 114 | +| "Environment variables not set" | Set `MCP_GITHUB_CLIENT_ID` and `MCP_GITHUB_CLIENT_SECRET` | |
| 115 | +| "Port already in use" | Change port: `--port=8001` | |
| 116 | +| "GitHub callback failed" | Update GitHub app callback to `http://localhost:9000/github/callback` | |
| 117 | +| "Token introspection failed" | Start Authorization Server first | |
| 118 | +| "Client can't discover Authorization Server" | Check Resource Server is configured with `--auth-server` | |
| 119 | +| "ModuleNotFoundError: No module named 'mcp_simple_auth'" | Run commands from the `simple-auth` directory as shown above | |
| 120 | +| "Resource Server exits immediately" | **Fixed:** This issue was caused by FastMCP auth configuration. The current version should work correctly. | |
90 | 121 |
|
91 | | -You can use [Inspector](https://github.com/modelcontextprotocol/inspector) to test Auth |
|
0 commit comments