Skip to content

Commit 8f9a0db

Browse files
committed
Fix examples + doc tweaks
1 parent 500c263 commit 8f9a0db

File tree

6 files changed

+240
-242
lines changed

6 files changed

+240
-242
lines changed

docs/endpoints.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Complete listing of all endpoints provided by each server in the architecture.
44

5-
## Auth Server (Port 3001)
5+
## Auth Server
66

77
Standalone OAuth 2.0 authorization server that handles authentication and token management.
88

@@ -37,7 +37,7 @@ Local simulation of upstream IDP (would be external in production):
3737

3838
---
3939

40-
## MCP Server (Port 3232)
40+
## MCP Server
4141

4242
MCP resource server that implements the Model Context Protocol with delegated authentication.
4343

docs/oauth-architecture-patterns.md

Lines changed: 16 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ This document describes different OAuth 2.0 architecture patterns for MCP server
66

77
Per the MCP specification, "the authorization server may be hosted with the resource server or as a separate entity." This leads to two primary patterns for implementing OAuth in MCP servers.
88

9-
## Pattern 1: Separate Authorization Server (Implemented)
9+
## Pattern 1: Separate Authorization Server (Recommended)
1010

11-
The current implementation uses this production-ready pattern with separate authorization and resource servers.
11+
The current implementation demonstrates this pattern with separate authorization and resource servers. (Note: the authorization server is for demonstration purposes only.)
1212

1313
### Architecture
1414

@@ -19,173 +19,51 @@ The current implementation uses this production-ready pattern with separate auth
1919
│ │ │ (port 3001) │validate │ (port 3232) │
2020
│ │<────────│ │ │ │
2121
│ │ token │ Issues tokens │ │ Serves MCP │
22-
│ │ │ │ │ resources │
22+
│ │ └──────────────────┘ │ resources │
2323
│ │────────────────────────────────────> │ │
2424
│ │ MCP requests with token │ │
2525
└─────────────┘ └─────────────────┘
2626
```
2727

2828
### Components
2929

30-
1. **Authorization Server** (port 3001)
30+
1. **Demo Authorization Server** (port 3001)
3131
- Handles OAuth 2.0 authorization flow
3232
- Issues and manages tokens
3333
- Provides token introspection endpoint (RFC 7662)
34-
- Can be replaced with Auth0, Okta, Google OAuth, etc.
34+
- Should be replaced with Auth0, Okta, Google OAuth, etc.
3535

3636
2. **MCP Resource Server** (port 3232)
3737
- Serves MCP protocol resources
3838
- Validates tokens via introspection
3939
- Contains no OAuth authorization code
4040
- Focuses purely on MCP functionality
4141

42-
### Benefits
42+
### Using a Commercial Auth Provider
4343

44-
- **Standards Compliance**: Follows OAuth 2.0 best practices
45-
- **Flexibility**: Easy to swap auth providers
46-
- **Scalability**: Servers scale independently
47-
- **Security**: Clear security boundaries
48-
- **Maintainability**: Separation of concerns
49-
50-
### Real-World Use Cases
51-
52-
- **SaaS Applications**: Using Auth0 or Okta for authentication
53-
- **Enterprise**: Integrating with corporate SSO (SAML, LDAP)
54-
- **Social Login**: Google, GitHub, Facebook authentication
55-
- **Cloud Native**: AWS Cognito, Azure AD integration
56-
57-
### Implementation Details
58-
59-
The MCP server validates tokens by calling the auth server's `/introspect` endpoint:
60-
61-
```typescript
62-
// In MCP server
63-
const response = await fetch(`${AUTH_SERVER_URL}/introspect`, {
64-
method: 'POST',
65-
headers: {
66-
'Content-Type': 'application/x-www-form-urlencoded',
67-
},
68-
body: `token=${accessToken}`
69-
});
44+
Replacing the demo auth server with a commercial provider:
7045

71-
const introspection = await response.json();
72-
if (introspection.active) {
73-
// Token is valid, extract user info
74-
const userId = introspection.sub;
75-
}
76-
```
46+
1. **Configure provider**: Set up OAuth app in commercial provider (e.g. Auth0/Okta)
47+
2. **Update metadata URL**: Point to provider's discovery endpoint
48+
3. **Configure introspection**: Set up token validation
49+
4. **Update redirect URIs**: Configure allowed callbacks
50+
5. **Migrate users**: Import existing users if needed
51+
6. **Test integration**: Verify full OAuth flow
7752

7853
---
7954

80-
## Pattern 2: Embedded Authorization Server (Alternative)
81-
82-
An alternative pattern where the OAuth server is embedded within the MCP server. This demonstrates a self-hosted OAuth 2.1 authorization server running in the same process as the MCP server.
83-
84-
### Architecture
85-
86-
```
87-
┌─────────────┐ ┌─────────────────────────┐
88-
│ │ OAuth │ │
89-
│ MCP Client │────────>│ MCP Server │
90-
│ │ │ ┌──────────────────┐ │
91-
│ │<────────│ │ OAuth Server │ │
92-
│ │ token │ └──────────────────┘ │
93-
│ │ │ ┌──────────────────┐ │
94-
│ │────────>│ │ MCP Resources │ │
95-
│ │ MCP │ └──────────────────┘ │
96-
└─────────────┘ └─────────────────────────┘
97-
```
98-
99-
### Upstream Delegation Pattern
100-
101-
Embedded OAuth often delegates user authentication to an upstream identity provider while maintaining control over token issuance:
102-
103-
```
104-
MCP Client MCP+OAuth Server Upstream IDP
105-
│ │ (Corporate SSO)
106-
│──1. /authorize───────────────>│ │
107-
│<───(show auth page)───────────│ │
108-
│ │ │
109-
│──2. Click "Continue"──────────>│ │
110-
│<──redirect to upstream────────│ │
111-
│ │ │
112-
│──3. /upstream/authorize────────────────────────────────────────>│
113-
│<──(authenticate user)──────────────────────────────────────────│
114-
│──4. Provide credentials────────────────────────────────────────>│
115-
│<──redirect with userId─────────────────────────────────────────│
116-
│ │ │
117-
│──5. /callback with userId───────>│ │
118-
│ │──(validate userId) │
119-
│ │──(issue MCP tokens) │
120-
│<──redirect with auth code──────│ │
121-
│ │ │
122-
│──6. /token (exchange code)─────>│ │
123-
│<──MCP access token─────────────│ │
124-
```
125-
126-
### Characteristics
127-
128-
- **Single Server**: OAuth and MCP in one process
129-
- **Port**: Typically runs on single port (e.g., 3232)
130-
- **Token Validation**: In-process, direct database access
131-
- **Deployment**: Simpler, fewer moving parts
132-
- **Upstream Delegation**: Can delegate authentication to corporate SSO while controlling token issuance
55+
## Pattern 2: Embedded Authorization Server (Alternative/Legacy)
13356

134-
### Benefits
57+
The MCP spec describes an alternative pattern where the OAuth server is embedded within the MCP server. However, this pattern is not recommended in the general case, and is not demonstrated in this codebase.
13558

136-
- **Simplicity**: Single server to deploy and manage
137-
- **Performance**: No network hop for token validation
138-
- **Self-Contained**: All functionality in one codebase
139-
- **Control**: Full control over token issuance while leveraging existing identity infrastructure
140-
141-
### Drawbacks
142-
143-
- **Coupling**: Auth and MCP logic intertwined
144-
- **Scalability**: Can't scale auth independently
145-
- **Flexibility**: Harder to switch auth providers
146-
- **Updates**: Auth changes require MCP server updates
147-
148-
### Use Cases
59+
### Possible Use Cases
14960

15061
- **Enterprise Deployments**: Organizations needing control over OAuth token issuance while leveraging existing corporate identity infrastructure (LDAP, Active Directory, SAML)
15162
- **Proof of Concepts**: Quick prototypes and demonstrations
15263
- **Small Deployments**: Internal tools with simple auth needs
15364
- **Isolated Systems**: Air-gapped environments without external connectivity
15465
- **Custom Auth Requirements**: Specialized authentication needs not met by standard providers
15566

156-
### Typical Configuration
157-
158-
Environment variables for embedded pattern:
159-
```bash
160-
BASE_URI=http://localhost:3232 # Single server URL
161-
PORT=3232 # Single port for OAuth + MCP
162-
REDIS_URL=redis://localhost:6379 # Session storage
163-
UPSTREAM_IDP_URL=https://corp.sso # Optional: upstream identity provider
164-
```
165-
166-
### Code Organization
167-
168-
Typical structure for embedded OAuth implementation:
169-
```
170-
src/
171-
├── index.ts # Main entry point (MCP + OAuth + routing)
172-
├── auth/
173-
│ ├── provider.ts # OAuth server implementation
174-
│ └── auth-core.ts # Token generation, PKCE utilities
175-
├── services/
176-
│ ├── mcp.ts # MCP protocol implementation
177-
│ ├── auth.ts # Auth service integration
178-
│ ├── redis-auth.ts # Redis auth operations
179-
│ └── redisTransport.ts # Redis-backed transport
180-
├── handlers/
181-
│ ├── oauth.ts # OAuth endpoints (/authorize, /token)
182-
│ ├── mcp-shttp.ts # Streamable HTTP handler
183-
│ ├── mcp-sse.ts # SSE handler
184-
│ └── upstream-idp.ts # Upstream IDP integration
185-
└── utils/
186-
└── logger.ts # Structured logging
187-
```
188-
18967
---
19068

19169
## Comparison
@@ -195,42 +73,11 @@ src/
19573
| **Architecture** | 2+ servers | 1 server |
19674
| **OAuth endpoints** | On auth server | On MCP server |
19775
| **Token validation** | Remote (introspection) | In-process |
198-
| **Deployment** | More complex | Simpler |
199-
| **Scalability** | Independent scaling | Coupled scaling |
200-
| **Provider integration** | Easy (standard APIs) | Difficult |
201-
| **Code organization** | Clear separation | Mixed concerns |
202-
| **Network hops** | Additional for validation | None for validation |
20376
| **Upstream IDP support** | Via auth server | Direct integration |
20477
| **Production readiness** | ✅ Recommended | ⚠️ Limited use cases |
20578

20679
---
20780

208-
## Migration Path
209-
210-
### From Embedded to Separate
211-
212-
If starting with embedded OAuth, migration to separate servers involves:
213-
214-
1. **Extract auth code**: Move OAuth handlers to separate service
215-
2. **Implement introspection**: Add RFC 7662 endpoint
216-
3. **Update MCP server**: Replace in-process validation with introspection calls
217-
4. **Update configuration**: Point MCP server to auth server URL
218-
5. **Migrate upstream IDP**: Move delegation logic to auth server
219-
6. **Test thoroughly**: Ensure token flow works correctly
220-
221-
### From Separate to Commercial Provider
222-
223-
Replacing the demo auth server with a commercial provider:
224-
225-
1. **Configure provider**: Set up OAuth app in Auth0/Okta
226-
2. **Update metadata URL**: Point to provider's discovery endpoint
227-
3. **Configure introspection**: Set up token validation
228-
4. **Update redirect URIs**: Configure allowed callbacks
229-
5. **Migrate users**: Import existing users if needed
230-
6. **Test integration**: Verify full OAuth flow
231-
232-
---
233-
23481
## Best Practices
23582

23683
1. **Use separate servers** for production deployments

docs/oauth-flow.md

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -194,18 +194,6 @@ This ensures only the client that initiated the flow can exchange the code, even
194194

195195
---
196196

197-
## Architecture Benefits
198-
199-
The separate server architecture provides:
200-
201-
1. **Standards Compliance**: Follows OAuth 2.0 best practices for resource/authorization server separation
202-
2. **Flexibility**: Auth server can be replaced with Auth0, Okta, or other providers
203-
3. **Scalability**: Auth and MCP servers can scale independently based on load
204-
4. **Security**: Token validation via introspection endpoint (RFC 7662)
205-
5. **Maintainability**: Clear separation of authentication and business logic
206-
207-
---
208-
209197
## References
210198

211199
- [RFC 6749: OAuth 2.0 Framework](https://datatracker.ietf.org/doc/html/rfc6749)

examples/README.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,21 @@ Shell script demonstrating API interactions using curl.
2929
# Make executable
3030
chmod +x curl-examples.sh
3131

32-
# Register client (step 1)
32+
# Step 1: Register OAuth client (automatic when no token provided)
3333
./curl-examples.sh
3434

35-
# After getting token (via MCP Inspector)
35+
# Step 2: Initialize MCP session (after getting token via MCP Inspector or client.js)
3636
./curl-examples.sh YOUR_ACCESS_TOKEN
3737

38-
# With session ID
38+
# Step 3: Run all examples (with session ID from step 2)
3939
./curl-examples.sh YOUR_ACCESS_TOKEN YOUR_SESSION_ID
4040
```
4141

42+
The script guides you through the process:
43+
- First run registers an OAuth client automatically
44+
- Second run initializes an MCP session and returns a session ID
45+
- Third run executes all the example MCP operations
46+
4247
### client.js
4348

4449
Node.js client showing programmatic interaction with the MCP server.
@@ -59,6 +64,20 @@ chmod +x client.js
5964
./client.js
6065
```
6166

67+
**Note:** When you complete the OAuth flow in your browser, you'll be redirected to `http://localhost:8080/callback` which will show "site can't be reached". This is expected! Simply copy the authorization code from the URL in your browser's address bar (the long string after `code=`). The script will exchange this for an access token and display it for use with other tools.
68+
69+
## Understanding OAuth Tokens
70+
71+
**Authorization Code** vs **Access Token**:
72+
- **Authorization Code**: The temporary code you get from the browser redirect (e.g., `302a80e8...`)
73+
- One-time use only
74+
- Must be exchanged for an access token
75+
- Expires quickly (usually within minutes)
76+
- **Access Token**: The actual bearer token for API authentication (e.g., `mcp_at_...`)
77+
- Used in the `Authorization: Bearer` header
78+
- Valid for 7 days
79+
- What you need for `curl-examples.sh`
80+
6281
## Getting an Access Token
6382

6483
### Option 1: MCP Inspector (Easiest)

0 commit comments

Comments
 (0)