|
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 |
| 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** |
12 | 13 |
|
| 14 | +**Set environment variables:** |
| 15 | +```bash |
| 16 | +export MCP_GITHUB_CLIENT_ID="your_client_id_here" |
| 17 | +export MCP_GITHUB_CLIENT_SECRET="your_client_secret_here" |
| 18 | +``` |
13 | 19 |
|
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 |
| 20 | +--- |
23 | 21 |
|
24 |
| -## Required Environment Variables |
| 22 | +## Running the Servers |
25 | 23 |
|
26 |
| -You MUST set these environment variables before running the server: |
| 24 | +### Step 1: Start Authorization Server |
27 | 25 |
|
28 | 26 | ```bash
|
29 |
| -export MCP_GITHUB_GITHUB_CLIENT_ID="your_client_id_here" |
30 |
| -export MCP_GITHUB_GITHUB_CLIENT_SECRET="your_client_secret_here" |
| 27 | +# Navigate to the simple-auth directory |
| 28 | +cd examples/servers/simple-auth |
| 29 | + |
| 30 | +# Start Authorization Server on port 9000 |
| 31 | +uv run mcp-simple-auth-as --port=9000 |
31 | 32 | ```
|
32 | 33 |
|
33 |
| -The server will not start without these environment variables properly set. |
| 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`) |
34 | 39 |
|
| 40 | +--- |
35 | 41 |
|
36 |
| -## Running the Server |
| 42 | +### Step 2: Start Resource Server (MCP Server) |
37 | 43 |
|
38 | 44 | ```bash
|
39 |
| -# Set environment variables first (see above) |
| 45 | +# In another terminal, navigate to the simple-auth directory |
| 46 | +cd examples/servers/simple-auth |
40 | 47 |
|
41 |
| -# Run the server |
42 |
| -uv run mcp-simple-auth |
| 48 | +# Start Resource Server on port 8001, connected to Authorization Server |
| 49 | +uv run mcp-simple-auth-rs --port=8001 --auth-server=http://localhost:9000 --transport=streamable-http |
43 | 50 | ```
|
44 | 51 |
|
45 |
| -The server will start on `http://localhost:8000`. |
46 |
| - |
47 |
| -### Transport Options |
48 | 52 |
|
49 |
| -This server supports multiple transport protocols that can run on the same port: |
| 53 | +### Step 3: Test with Client |
50 | 54 |
|
51 |
| -#### SSE (Server-Sent Events) - Default |
52 | 55 | ```bash
|
53 |
| -uv run mcp-simple-auth |
54 |
| -# or explicitly: |
55 |
| -uv run mcp-simple-auth --transport sse |
| 56 | +cd examples/clients/simple-auth-client |
| 57 | +# Start client with streamable HTTP |
| 58 | +MCP_SERVER_PORT=8001 MCP_TRANSPORT_TYPE=streamable_http uv run mcp-simple-auth-client |
56 | 59 | ```
|
57 | 60 |
|
58 |
| -SSE transport provides endpoint: |
59 |
| -- `/sse` |
60 | 61 |
|
61 |
| -#### Streamable HTTP |
| 62 | +## How It Works |
| 63 | + |
| 64 | +### RFC 9728 Discovery |
| 65 | + |
| 66 | +**Client → Resource Server:** |
62 | 67 | ```bash
|
63 |
| -uv run mcp-simple-auth --transport streamable-http |
| 68 | +curl http://localhost:8001/.well-known/oauth-protected-resource |
| 69 | +``` |
| 70 | +```json |
| 71 | +{ |
| 72 | + "resource": "http://localhost:8001", |
| 73 | + "authorization_servers": ["http://localhost:9000"] |
| 74 | +} |
64 | 75 | ```
|
65 | 76 |
|
66 |
| -Streamable HTTP transport provides endpoint: |
67 |
| -- `/mcp` |
| 77 | +**Client → Authorization Server:** |
| 78 | +```bash |
| 79 | +curl http://localhost:9000/.well-known/oauth-authorization-server |
| 80 | +``` |
| 81 | +```json |
| 82 | +{ |
| 83 | + "issuer": "http://localhost:9000", |
| 84 | + "authorization_endpoint": "http://localhost:9000/authorize", |
| 85 | + "token_endpoint": "http://localhost:9000/token" |
| 86 | +} |
| 87 | +``` |
68 | 88 |
|
| 89 | +## Legacy MCP Server as Authorization Server (Backwards Compatibility) |
69 | 90 |
|
70 |
| -This ensures backward compatibility without needing multiple server instances. When using SSE transport (`--transport sse`), only the `/sse` endpoint is available. |
| 91 | +For backwards compatibility with older MCP implementations, a legacy server is provided that acts as an Authorization Server (following the old spec where MCP servers could optionally provide OAuth): |
71 | 92 |
|
72 |
| -## Available Tool |
| 93 | +### Running the Legacy Server |
73 | 94 |
|
74 |
| -### get_user_profile |
| 95 | +```bash |
| 96 | +# Start legacy authorization server on port 8002 |
| 97 | +uv run mcp-simple-auth-legacy --port=8002 |
| 98 | +``` |
| 99 | + |
| 100 | +**Differences from the new architecture:** |
| 101 | +- **MCP server acts as AS:** The MCP server itself provides OAuth endpoints (old spec behavior) |
| 102 | +- **No separate RS:** The server handles both authentication and MCP tools |
| 103 | +- **Local token validation:** Tokens are validated internally without introspection |
| 104 | +- **No RFC 9728 support:** Does not provide `/.well-known/oauth-protected-resource` |
| 105 | +- **Direct OAuth discovery:** OAuth metadata is at the MCP server's URL |
75 | 106 |
|
76 |
| -The only tool in this simple example. Returns the authenticated user's GitHub profile information. |
| 107 | +### Testing with Legacy Server |
| 108 | + |
| 109 | +```bash |
| 110 | +# Test with client (will automatically fall back to legacy discovery) |
| 111 | +cd examples/clients/simple-auth-client |
| 112 | +MCP_SERVER_PORT=8002 MCP_TRANSPORT_TYPE=streamable_http uv run mcp-simple-auth-client |
| 113 | +``` |
77 | 114 |
|
78 |
| -**Required scope**: `user` |
| 115 | +The client will: |
| 116 | +1. Try RFC 9728 discovery at `/.well-known/oauth-protected-resource` (404 on legacy server) |
| 117 | +2. Fall back to direct OAuth discovery at `/.well-known/oauth-authorization-server` |
| 118 | +3. Complete authentication with the MCP server acting as its own AS |
79 | 119 |
|
80 |
| -**Returns**: GitHub user profile data including username, email, bio, etc. |
| 120 | +This ensures existing MCP servers (which could optionally act as Authorization Servers under the old spec) continue to work while the ecosystem transitions to the new architecture where MCP servers are Resource Servers only. |
81 | 121 |
|
| 122 | +## Manual Testing |
82 | 123 |
|
83 |
| -## Troubleshooting |
| 124 | +### Test Discovery |
| 125 | +```bash |
| 126 | +# Test Resource Server discovery endpoint (new architecture) |
| 127 | +curl -v http://localhost:8001/.well-known/oauth-protected-resource |
84 | 128 |
|
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`) |
| 129 | +# Test Authorization Server metadata |
| 130 | +curl -v http://localhost:9000/.well-known/oauth-authorization-server |
| 131 | +``` |
90 | 132 |
|
91 |
| -You can use [Inspector](https://github.com/modelcontextprotocol/inspector) to test Auth |
| 133 | +### Test Token Introspection |
| 134 | +```bash |
| 135 | +# After getting a token through OAuth flow: |
| 136 | +curl -X POST http://localhost:9000/introspect \ |
| 137 | + -H "Content-Type: application/x-www-form-urlencoded" \ |
| 138 | + -d "token=your_access_token" |
| 139 | +``` |
0 commit comments