Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1bcb85b
Phase 1: Add configuration for integrated/separate auth modes
bhosmer-ant Sep 4, 2025
98cec05
Phase 2: Extract shared auth logic
bhosmer-ant Sep 4, 2025
0135abd
Phase 3: Implement MCP server mode switching
bhosmer-ant Sep 4, 2025
03deb88
Fix build and lint issues
bhosmer-ant Sep 4, 2025
4771c6e
Add retry logic and token caching
bhosmer-ant Sep 4, 2025
5c408eb
Phase 4: Create standalone authorization server
bhosmer-ant Sep 5, 2025
3f930c5
Phase 7: Complete README documentation for dual auth modes
bhosmer-ant Sep 5, 2025
b796560
add docker-compose.yml
bhosmer-ant Sep 5, 2025
d368c8d
address comments:
bhosmer-ant Sep 11, 2025
9ffe376
Fix endpoint consistency and documentation accuracy
bhosmer-ant Sep 12, 2025
40773bd
Add end-to-end verification scripts and fix server issues
bhosmer-ant Sep 12, 2025
1e47b07
Update documentation for current implementation
bhosmer-ant Sep 12, 2025
890beed
Add rate limiting and improve e2e testing workflow
bhosmer-ant Sep 12, 2025
ecd82f4
Add rate limiting to auth server static file endpoint
bhosmer-ant Sep 12, 2025
4e3414f
Fix undefined staticFileRateLimit in auth server
bhosmer-ant Sep 12, 2025
fdbf40b
Simplify build scripts to catch all compilation errors
bhosmer-ant Sep 12, 2025
5f545ce
Fix CI build by using public npm registry in package-lock.json
bhosmer-ant Sep 12, 2025
67d9a94
improvements to README.md
bhosmer-ant Sep 12, 2025
56a43ac
Fix OAuth metadata endpoint in separate mode
bhosmer-ant Sep 15, 2025
b32d638
Consolidate TypeScript build configuration
bhosmer-ant Sep 15, 2025
4fe1374
Add debug logging for OAuth flow troubleshooting
bhosmer-ant Sep 15, 2025
4a081bc
Improve e2e tests with OAuth flow validation
bhosmer-ant Sep 15, 2025
34fe20e
Implement Redis namespace isolation for auth and MCP keys
bhosmer-ant Sep 15, 2025
e393cb2
Add OAuth protected resource metadata endpoint for separate mode
bhosmer-ant Sep 15, 2025
dbd3e9a
Revert OAuth metadata change for backwards compatibility
bhosmer-ant Sep 23, 2025
a735b98
Add comprehensive token validation to ExternalAuthVerifier
bhosmer-ant Sep 23, 2025
67def73
Fix token audience validation in separate auth mode
bhosmer-ant Sep 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.integrated
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
AUTH_MODE=integrated
BASE_URI=http://localhost:3232
PORT=3232
REDIS_URL=redis://localhost:6379
6 changes: 6 additions & 0 deletions .env.separate
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
AUTH_MODE=separate
BASE_URI=http://localhost:3232
PORT=3232
REDIS_URL=redis://localhost:6379
AUTH_SERVER_URL=http://localhost:3001
AUTH_SERVER_PORT=3001
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,6 @@ dist
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

# Claude config directory
.claude/
192 changes: 184 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,146 @@ This server serves as both primarily as a learning resource, and an example impl
- **Horizontal Scaling**: Any instance can handle any request

### Authentication & Security
- **Dual Mode Support**: Run with integrated or separate authorization server
- **[OAuth 2.0](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization)**: Complete authorization flow with PKCE support
- **Fake Auth Provider**: Built-in testing provider with localStorage user management
- **Session Ownership**: User isolation and access control
- **External Auth Ready**: Demonstrates integration with external OAuth providers
- **Session Ownership**: User isolation and access control
- **Security Headers**: CSP, HSTS, X-Frame-Options, and more
- **Bearer Token Auth**: Middleware for protected endpoints

## Authentication Modes

The Everything Server supports two authentication modes to demonstrate different MCP deployment patterns:

### Integrated Mode (Default)
The MCP server acts as its own OAuth 2.0 authorization server. This is simpler to deploy and suitable for standalone MCP servers.

```bash
npm run dev:integrated
```

### Separate Mode
The MCP server delegates authentication to a standalone authorization server. This demonstrates how MCP servers can integrate with existing OAuth infrastructure. See [auth-server/README.md](auth-server/README.md) for more details about the standalone auth server.

```bash
# Start both the auth server and MCP server
npm run dev:with-separate-auth

# Or run them separately:
# Terminal 1: Start the authorization server
npm run dev:auth-server

# Terminal 2: Start the MCP server in separate mode
npm run dev:separate
```

In production, the separate authorization server would typically be replaced with:
- Corporate SSO (Auth0, Okta)
- Cloud providers (AWS Cognito, Azure AD)
- Social providers (Google, GitHub)

### Testing with MCP Inspector

The MCP Inspector is a web-based tool for testing MCP servers. You can run it locally:
```bash
npx -y @modelcontextprotocol/inspector
```

#### Integrated Mode
```bash
# 1. Start Redis
docker compose up -d

# 2. Start the server
npm run dev:integrated

# 3. Open MCP Inspector
npx -y @modelcontextprotocol/inspector

# 4. Connect and test:
# - Connect to http://localhost:3232
# - Navigate to the Auth tab
# - Complete the OAuth flow
# - All auth endpoints will be served from :3232
```

#### Separate Mode
```bash
# 1. Start Redis
docker compose up -d

# 2. Start both servers
npm run dev:with-separate-auth

# 3. Open MCP Inspector
npx -y @modelcontextprotocol/inspector

# 4. Connect and test:
# - Connect to http://localhost:3232
# - Navigate to the Auth tab
# - The auth flow will redirect to :3001 for authentication
# - After auth, tokens from :3001 will be used on :3232
```

### Architecture Diagrams

#### Integrated Mode
```
┌──────────┐ ┌───────────────────┐
│ MCP │◀────▶│ MCP Server │
│ Inspector│ │ (port 3232) │
└──────────┘ │ │
│ - OAuth Server │
│ - Resource Server │
└───────────────────┘
```

#### Separate Mode
```
┌──────────┐ ┌───────────────────┐ ┌─────────────────┐
│ MCP │◀────▶│ MCP Server │◀────▶│ Auth Server │
│ Inspector│ │ (port 3232) │ │ (port 3001) │
└──────────┘ │ │ │ │
│ │ - Resource Server │ │ - OAuth Server │
└───────────▶│ │ │ │
└───────────────────┘ └─────────────────┘
```

## Installation

### Prerequisites
- Node.js >= 16
- Redis server
- Redis server (see Redis setup below)
- npm or yarn

### Redis Setup
The server requires Redis for session management and message routing.

**Option 1: Docker Compose (Recommended)**

Install a Docker runtime:
- **macOS**: [OrbStack](https://orbstack.dev/) - Fast, lightweight, and free
```bash
brew install orbstack
# Or download from https://orbstack.dev/download
```
- **Windows/Linux**: [Docker Desktop](https://www.docker.com/products/docker-desktop)

Start Redis:
```bash
# see docker-compose.yml
docker compose up -d
```

**Option 2: Local Installation**
```bash
# macOS
brew install redis && brew services start redis

# Ubuntu/Debian
sudo apt-get install redis-server && sudo systemctl start redis
```

### Setup
```bash
# Clone the repository
Expand All @@ -62,30 +189,79 @@ cp .env.example .env

### Configuration
Environment variables (`.env` file):
```
PORT=3232 # Server port
```bash
# Server Configuration
PORT=3232 # MCP server port
BASE_URI=http://localhost:3232 # Base URI for OAuth redirects
REDIS_HOST=localhost # Redis server host
REDIS_PORT=6379 # Redis server port
REDIS_PASSWORD= # Redis password (if required)

# Redis Configuration
REDIS_URL=redis://localhost:6379 # Redis connection URL

# Authentication Mode (integrated | separate)
AUTH_MODE=integrated # Default: integrated mode

# Separate Mode Configuration (only used when AUTH_MODE=separate)
AUTH_SERVER_URL=http://localhost:3001 # External auth server URL
AUTH_SERVER_PORT=3001 # Auth server port (for standalone server)
```

**Pre-configured environment files:**
- `.env.integrated` - Configuration for integrated mode
- `.env.separate` - Configuration for separate mode

```bash
# Use integrated mode
cp .env.integrated .env

# Use separate mode
cp .env.separate .env
```

## Development

### Commands

#### Development
```bash
# Start development server with hot reload
npm run dev

# Start in integrated mode (MCP server as OAuth server)
npm run dev:integrated

# Start in separate mode (external auth server)
npm run dev:separate

# Start standalone authorization server
npm run dev:auth-server

# Start both auth server and MCP server in separate mode
npm run dev:with-separate-auth

# Start development server with debugging
npm run dev:break
```

#### Build & Production
```bash
# Build TypeScript to JavaScript
npm run build

# Build authorization server
npm run build:auth-server

# Build everything
npm run build:all

# Run production server
npm start

# Run production auth server
npm run start:auth-server
```

#### Testing & Quality
```bash
# Run linting
npm run lint

Expand Down
89 changes: 89 additions & 0 deletions auth-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# MCP Standalone Authorization Server

This is a demonstration OAuth 2.0 authorization server for MCP.

## Purpose

This server demonstrates how MCP servers can delegate authentication to a separate
authorization server (Mode 2 in our implementation). In production environments,
you would typically use established OAuth providers like:

- Auth0
- Okta
- Google OAuth
- GitHub OAuth
- Microsoft Azure AD

## Architecture

When running in separate mode, the architecture looks like:

1. MCP Client (e.g., Inspector) discovers auth server URL from MCP server metadata
2. Client registers and authenticates directly with this auth server
3. Auth server issues tokens
4. MCP server validates tokens by calling this auth server's introspection endpoint

## Endpoints

- `/.well-known/oauth-authorization-server` - OAuth 2.0 server metadata
- `/oauth/authorize` - Authorization endpoint
- `/oauth/token` - Token endpoint
- `/oauth/register` - Dynamic client registration
- `/oauth/introspect` - Token introspection (for MCP server validation)
- `/fakeupstreamauth/authorize` - Fake upstream auth page (demo only)
- `/fakeupstreamauth/callback` - Fake upstream callback (demo only)
- `/health` - Health check endpoint

## Development

This server shares Redis with the MCP server for development convenience.
In production, these would typically be separate.

## Running the Auth Server

### Standalone
```bash
# From the repository root
npm run dev:auth-server
```

### With MCP Server (Separate Mode)
```bash
# Start both servers together
npm run dev:with-separate-auth
```

## Testing

### Health Check
```bash
curl http://localhost:3001/health
```

### OAuth Metadata
```bash
curl http://localhost:3001/.well-known/oauth-authorization-server
```

### With MCP Inspector
1. Start this auth server: `npm run dev:auth-server`
2. Start MCP server in separate mode: `AUTH_MODE=separate npm run dev`
3. Open Inspector: `npx -y @modelcontextprotocol/inspector`
4. Connect to `http://localhost:3232`
5. Auth flow will redirect to this server (port 3001)

## Configuration

The auth server uses the same environment variables as the main server:
- `AUTH_SERVER_PORT` - Port to run on (default: 3001)
- `AUTH_SERVER_URL` - Base URL (default: http://localhost:3001)
- `REDIS_URL` - Redis connection (shared with MCP server)

## Production Considerations

In production:
- Use real OAuth providers instead of this demonstration server
- Separate Redis instances for auth and resource servers
- Enable HTTPS with proper certificates
- Implement proper rate limiting and monitoring
- Use secure client secrets and token rotation
Loading
Loading