Fix endpoint consistency and documentation accuracy

- Remove /oauth prefix from introspect endpoint to match SDK pattern
- Fix auth-server endpoints: /introspect not /oauth/introspect
- Update external-verifier to call correct introspect endpoint
- Add 30-day expiry to client registration (REDIS_EXPIRY_TIMES.CLIENT_REGISTRATION)
- Remove inaccurate scratch/ directory references from README
- Add backlinks from auth-server/README.md to main README sections
- Verified all implementation details against running servers and Redis data
This commit is contained in:
Basil Hosmer 2025-09-11 21:08:29 -04:00
commit 9ffe376932
No known key found for this signature in database
4 changed files with 269 additions and 286 deletions

508
README.md
View file

@ -9,7 +9,7 @@ A comprehensive example implementation of a scalable Model Context Protocol (MCP
The Everything Server is an open-source reference implementation that showcases:
- **Complete [MCP Protocol](https://modelcontextprotocol.io/specification) Support**: All MCP features including tools, resources, prompts, sampling, completions, and logging
- **Multiple [Transport Methods](https://modelcontextprotocol.io/docs/concepts/transports)**: Streamable HTTP (SHTTP) and Server-Sent Events (SSE)
- **Comprehensive Auth**: OAuth 2.0 with fake upstream provider for testing
- **Dual Authentication Modes**: Integrated and separate authorization server support
- **Horizontal Scalability**: Redis-backed session management for multi-instance deployments
This server serves as both primarily as a learning resource, and an example implementation of a scalable remote MCP server.
@ -40,162 +40,6 @@ This server serves as both primarily as a learning resource, and an example impl
- **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/mcp
# - 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/mcp
# - 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
```mermaid
graph TD
Client["MCP Client<br/>(Inspector)"]
MCP["MCP Server<br/>(port 3232)<br/>• OAuth Server<br/>• Resource Server"]
Client <-->|"OAuth flow & MCP resources"| MCP
```
#### Separate Mode
```mermaid
graph TD
Client["MCP Client<br/>(Inspector)"]
MCP["MCP Server<br/>(port 3232)<br/>Resource Server"]
Auth["Auth Server<br/>(port 3001)<br/>OAuth Server"]
Client <-->|"1. Discover metadata"| MCP
Client <-->|"2. OAuth flow<br/>(register, authorize, token)"| Auth
Client <-->|"3. Use tokens for MCP resources"| MCP
MCP <-->|"Token validation<br/>(introspect)"| Auth
```
## OAuth Flow Analysis
### OAuth 2.0 + PKCE Flow Sequence
The server implements a complete OAuth 2.0 authorization code flow with PKCE. Here's how each step maps to data storage and expiry:
**1. Client Registration** (app setup - happens once)
```
App → Auth Server: "I want to use OAuth, here's my info"
Auth Server → App: "OK, your client_id is XYZ, client_secret is ABC"
```
- **Storage**: Client credentials for future OAuth flows
- **Expiry**: 30 days (long-lived app credentials)
**2. Authorization Request** (starts each OAuth flow)
```
User → App: "I want to connect to MCP server"
App → Auth Server: "User wants access, here's my PKCE challenge"
Auth Server: Stores pending authorization, shows auth page
```
- **Storage**: `PENDING_AUTHORIZATION` - temporary state during flow
- **Expiry**: 10 minutes (short-lived temporary state)
**3. Authorization Code Exchange** (completes OAuth flow)
```
User → Auth Server: "I approve this app"
Auth Server → App: "Here's your authorization code"
App → Auth Server: "Exchange code + PKCE verifier for tokens"
Auth Server → App: "Here are your access/refresh tokens"
```
- **Storage**: `TOKEN_EXCHANGE` - prevents replay attacks
- **Expiry**: 10 minutes (single-use, consumed immediately)
**4. Token Storage** (long-term user session)
```
Auth Server: Issues access_token + refresh_token
Server: Stores user installation with tokens
```
- **Storage**: `UPSTREAM_INSTALLATION` - the actual user session
- **Expiry**: 7 days (balances security vs usability)
**5. Token Refresh** (extends user session)
```
App → Auth Server: "My access token expired, here's my refresh token"
Auth Server → App: "Here's a new access token"
```
- **Storage**: `REFRESH_TOKEN` - mapping for token rotation
- **Expiry**: 7 days (matches installation lifetime)
### Data Lifecycle Hierarchy
**Timeline (shortest to longest expiry):**
1. **OAuth flow state** (10 minutes) - very temporary
2. **User sessions** (7 days) - medium-term
3. **Client credentials** (30 days) - long-term
This creates a logical hierarchy where each layer outlives the layers it supports.
## Installation
### Prerequisites
@ -239,13 +83,10 @@ cd example-remote-server
# Install dependencies
npm install
# Configure environment (optional)
cp .env.example .env
# Edit .env with your settings
```
### Configuration
## Configuration
Environment variables (`.env` file):
```bash
# Server Configuration
@ -275,6 +116,37 @@ cp .env.integrated .env
cp .env.separate .env
```
## 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)
## Development
### Commands
@ -327,108 +199,39 @@ npm run lint
npm test
```
### Project Structure
```
├── src/
│ ├── index.ts # Express app setup and routes
│ ├── config.ts # Configuration management
│ ├── redis.ts # Redis client setup
│ ├── auth/
│ │ └── provider.ts # OAuth auth provider implementation
│ ├── handlers/
│ │ ├── shttp.ts # Streamable HTTP handler
│ │ ├── sse.ts # SSE transport handler
│ │ ├── fakeauth.ts # Fake upstream auth handler
│ │ └── common.ts # Shared middleware
│ ├── services/
│ │ ├── mcp.ts # MCP server implementation
│ │ ├── auth.ts # Session ownership management
│ │ └── redisTransport.ts # Redis-backed transport
│ └── utils/
│ └── logger.ts # Structured logging
├── docs/
│ ├── streamable-http-design.md # SHTTP implementation details
│ └── user-id-system.md # Authentication flow documentation
├── scratch/ # Development scripts and tests
└── dist/ # Compiled JavaScript output
### Testing with MCP Inspector
The MCP Inspector is a web-based tool for testing MCP servers:
```bash
npx -y @modelcontextprotocol/inspector
```
## API Endpoints
#### Test Integrated Mode
```bash
# 1. Start Redis
docker compose up -d
### MCP Endpoints
- `GET/POST/DELETE /mcp` - Streamable HTTP transport endpoint
- `POST`: Initialize sessions or send messages
- `GET`: Establish SSE streams
- `DELETE`: Terminate sessions
- `GET /sse` - Legacy SSE transport endpoint
- `POST /message` - Legacy message endpoint for SSE transport
# 2. Start the server
npm run dev:integrated
### Authentication Endpoints
- `GET /fakeupstreamauth/authorize` - Fake OAuth authorization page
- `GET /fakeupstreamauth/redirect` - OAuth redirect handler
- OAuth 2.0 endpoints provided by MCP SDK auth router
### Headers
- `Mcp-Session-Id`: Session identifier for Streamable HTTP
- `Authorization: Bearer <token>`: OAuth access token
- Standard MCP headers as per protocol specification
## Authentication Flow
The server implements a complete [OAuth 2.0](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization) flow with a fake upstream provider for testing:
1. **Client Registration**: Clients register to obtain client_id and client_secret
2. **Authorization**: Users authenticate through `/fakeupstreamauth/authorize`
3. **User Management**: localStorage-based user ID system for testing
4. **Token Exchange**: Authorization codes exchanged for access tokens
5. **Session Creation**: Authenticated tokens create owned sessions
6. **Access Control**: Sessions are isolated by user ownership
See [docs/user-id-system.md](docs/user-id-system.md) for detailed authentication documentation.
## Transport Methods
### Streamable HTTP (Recommended)
Modern [transport](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http) supporting bidirectional communication over HTTP:
- Single endpoint for all operations
- Session management via headers
- Efficient message buffering
- Automatic reconnection support
See [docs/streamable-http-design.md](docs/streamable-http-design.md) for implementation details.
### Server-Sent Events (Legacy)
Backwards-compatible [transport](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#server-sent-events) using SSE:
- Separate endpoints for SSE streams and messages
- Session management via URL parameters
- Redis-backed message routing
- Real-time event delivery
## Scalability Architecture
The server is designed for horizontal scaling using Redis as the backbone:
### Session State Management
- **Redis Storage**: All session state stored in Redis
- **5-minute TTL**: Automatic session cleanup
- **Session Ownership**: User isolation via Redis keys
- **Stateless Servers**: Any instance can handle any request
### Message Routing
- **Pub/Sub Channels**: Redis channels for message distribution
- **Message Buffering**: Reliable delivery for disconnected clients
- **Connection State**: Tracked via pub/sub subscription counts
- **Automatic Cleanup**: No explicit cleanup required
### Redis Key Structure
```
session:{sessionId}:owner # Session ownership
mcp:shttp:toserver:{sessionId} # Client→Server messages
mcp:shttp:toclient:{sessionId}:{requestId} # Server→Client responses
mcp:control:{sessionId} # Control messages
# 3. Open MCP Inspector and connect to http://localhost:3232/mcp
# 4. Navigate to the Auth tab and complete the OAuth flow
# 5. All auth endpoints will be served from :3232
```
## Testing
#### Test Separate Mode
```bash
# 1. Start Redis
docker compose up -d
# 2. Start both servers
npm run dev:with-separate-auth
# 3. Open MCP Inspector and connect to http://localhost:3232/mcp
# 4. Navigate to the Auth tab
# 5. The auth flow will redirect to :3001 for authentication
# 6. After auth, tokens from :3001 will be used on :3232
```
### Running Tests
```bash
@ -449,12 +252,186 @@ npm test -- --coverage
- **Auth Tests**: OAuth flow and session ownership
- **Multi-user Tests**: User isolation and access control
### Manual Testing
The `scratch/` directory contains utility scripts for testing:
- `oauth.sh` - Test OAuth flows
- `simple-test-client.js` - Basic client implementation
- `test-shttp-client.ts` - Streamable HTTP testing
- `debug-mcp-flow.sh` - Debug MCP message flows
### Additional Testing
Use the MCP Inspector for interactive testing and debugging of OAuth flows, tool execution, and resource access.
## Architecture & Technical Details
### Authentication Architecture
#### Integrated Mode
```mermaid
graph TD
Client["MCP Client<br/>(Inspector)"]
MCP["MCP Server<br/>(port 3232)<br/>• OAuth Server<br/>• Resource Server"]
Client <-->|"OAuth flow & MCP resources"| MCP
```
#### Separate Mode
```mermaid
graph TD
Client["MCP Client<br/>(Inspector)"]
MCP["MCP Server<br/>(port 3232)<br/>Resource Server"]
Auth["Auth Server<br/>(port 3001)<br/>OAuth Server"]
Client <-->|"1. Discover metadata"| MCP
Client <-->|"2. OAuth flow<br/>(register, authorize, token)"| Auth
Client <-->|"3. Use tokens for MCP resources"| MCP
MCP <-->|"Token validation<br/>(introspect)"| Auth
```
### OAuth 2.0 + PKCE Flow Analysis
The server implements a complete OAuth 2.0 authorization code flow with PKCE. Here's how each step maps to data storage and expiry:
**1. Client Registration** (app setup - happens once)
```
App → Auth Server: "I want to use OAuth, here's my info"
Auth Server → App: "OK, your client_id is XYZ, client_secret is ABC"
```
- **Storage**: Client credentials for future OAuth flows
- **Expiry**: 30 days (long-lived app credentials)
**2. Authorization Request** (starts each OAuth flow)
```
User → App: "I want to connect to MCP server"
App → Auth Server: "User wants access, here's my PKCE challenge"
Auth Server: Stores pending authorization, shows auth page
```
- **Storage**: `PENDING_AUTHORIZATION` - temporary state during flow
- **Expiry**: 10 minutes (short-lived temporary state)
**3. Authorization Code Exchange** (completes OAuth flow)
```
User → Auth Server: "I approve this app"
Auth Server → App: "Here's your authorization code"
App → Auth Server: "Exchange code + PKCE verifier for tokens"
Auth Server → App: "Here are your access/refresh tokens"
```
- **Storage**: `TOKEN_EXCHANGE` - prevents replay attacks
- **Expiry**: 10 minutes (single-use, consumed immediately)
**4. Token Storage** (long-term user session)
```
Auth Server: Issues access_token + refresh_token
Server: Stores user installation with tokens
```
- **Storage**: `UPSTREAM_INSTALLATION` - the actual user session
- **Expiry**: 7 days (balances security vs usability)
**5. Token Refresh** (extends user session)
```
App → Auth Server: "My access token expired, here's my refresh token"
Auth Server → App: "Here's a new access token"
```
- **Storage**: `REFRESH_TOKEN` - mapping for token rotation
- **Expiry**: 7 days (matches installation lifetime)
#### Data Lifecycle Hierarchy
**Timeline (shortest to longest expiry):**
1. **OAuth flow state** (10 minutes) - very temporary
2. **User sessions** (7 days) - medium-term
3. **Client credentials** (30 days) - long-term
This creates a logical hierarchy where each layer outlives the layers it supports.
### Project Structure
```
├── src/ # MCP server code
│ ├── index.ts # Express app setup and routes
│ ├── config.ts # Configuration management
│ ├── redis.ts # Redis client setup
│ ├── auth/
│ │ ├── provider.ts # OAuth auth provider implementation
│ │ └── external-verifier.ts # External token verification
│ ├── handlers/
│ │ ├── shttp.ts # Streamable HTTP handler
│ │ ├── sse.ts # SSE transport handler
│ │ ├── fakeauth.ts # Fake upstream auth handler
│ │ └── common.ts # Shared middleware
│ ├── services/
│ │ ├── mcp.ts # MCP server implementation
│ │ ├── auth.ts # Auth service wrappers
│ │ └── redisTransport.ts # Redis-backed transport
│ └── utils/
│ └── logger.ts # Structured logging
├── auth-server/ # Standalone authorization server
│ ├── index.ts # Auth server main entry point
│ ├── README.md # Auth server documentation
│ └── tsconfig.json # TypeScript configuration
├── shared/ # Shared between both servers
│ ├── auth-core.ts # Core auth logic
│ ├── redis-auth.ts # Redis auth operations
│ └── types.ts # Shared type definitions
├── docs/
│ ├── streamable-http-design.md # SHTTP implementation details
│ └── user-id-system.md # Authentication flow documentation
└── dist/ # Compiled JavaScript output
```
### Scalability Architecture
The server is designed for horizontal scaling using Redis as the backbone:
#### Session State Management
- **Redis Storage**: All session state stored in Redis
- **5-minute TTL**: Automatic session cleanup
- **Session Ownership**: User isolation via Redis keys
- **Stateless Servers**: Any instance can handle any request
#### Message Routing
- **Pub/Sub Channels**: Redis channels for message distribution
- **Message Buffering**: Reliable delivery for disconnected clients
- **Connection State**: Tracked via pub/sub subscription counts
- **Automatic Cleanup**: No explicit cleanup required
#### Redis Key Structure
```
session:{sessionId}:owner # Session ownership
mcp:shttp:toserver:{sessionId} # Client→Server messages
mcp:shttp:toclient:{sessionId}:{requestId} # Server→Client responses
mcp:control:{sessionId} # Control messages
```
### Transport Methods
#### Streamable HTTP (Recommended)
Modern [transport](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http) supporting bidirectional communication over HTTP:
- Single endpoint for all operations
- Session management via headers
- Efficient message buffering
- Automatic reconnection support
See [docs/streamable-http-design.md](docs/streamable-http-design.md) for implementation details.
#### Server-Sent Events (Legacy)
Backwards-compatible [transport](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#server-sent-events) using SSE:
- Separate endpoints for SSE streams and messages
- Session management via URL parameters
- Redis-backed message routing
- Real-time event delivery
## API Reference
### MCP Endpoints
- `GET/POST/DELETE /mcp` - Streamable HTTP transport endpoint
- `POST`: Initialize sessions or send messages
- `GET`: Establish SSE streams
- `DELETE`: Terminate sessions
- `GET /sse` - Legacy SSE transport endpoint
- `POST /message` - Legacy message endpoint for SSE transport
### Authentication Endpoints (Integrated Mode Only)
- `GET /fakeupstreamauth/authorize` - Fake OAuth authorization page
- `GET /fakeupstreamauth/callback` - OAuth redirect handler
- OAuth 2.0 endpoints provided by MCP SDK auth router
### Headers
- `Mcp-Session-Id`: Session identifier for Streamable HTTP
- `Authorization: Bearer <token>`: OAuth access token
- Standard MCP headers as per protocol specification
## Security
@ -505,10 +482,11 @@ redis-cli GET "session:{sessionId}:owner"
```
### Debug Tools
- Development scripts in `scratch/` directory
- MCP Inspector for interactive debugging
- Comprehensive test suite
- Hot-reload development mode
- Source maps for debugging
- Redis monitoring commands
## Contributing

View file

@ -1,35 +1,32 @@
# MCP Standalone Authorization Server
This is a demonstration OAuth 2.0 authorization server for MCP.
This is a demonstration OAuth 2.0 authorization server for MCP's separate authentication mode.
## 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:
This server demonstrates how MCP servers can delegate authentication to a separate authorization server. See the main [README Authentication Modes](../README.md#authentication-modes) section for a complete overview of integrated vs separate modes.
- Auth0
- Okta
- Google OAuth
- GitHub OAuth
- Microsoft Azure AD
In production environments, you would typically use established OAuth providers like:
- Auth0, Okta
- Google OAuth, GitHub OAuth
- Microsoft Azure AD, AWS Cognito
## Architecture
When running in separate mode, the architecture looks like:
For detailed architecture information and OAuth flow analysis, see:
- [Authentication Modes](../README.md#authentication-modes) - Overview and comparison
- [OAuth 2.0 + PKCE Flow Analysis](../README.md#oauth-20--pkce-flow-analysis) - Step-by-step flow breakdown
- [Authentication Architecture](../README.md#authentication-architecture) - Visual diagrams
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
This auth server specifically implements the "Auth Server" component in the separate mode architecture diagram.
## 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)
- `/authorize` - Authorization endpoint
- `/token` - Token endpoint
- `/register` - Dynamic client registration
- `/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
@ -66,24 +63,32 @@ curl http://localhost:3001/.well-known/oauth-authorization-server
```
### With MCP Inspector
See the main [Testing with MCP Inspector](../README.md#testing-with-mcp-inspector) section for complete testing instructions for both modes.
**Quick test for this auth server:**
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/mcp`
5. Auth flow will redirect to this server (port 3001)
2. Start MCP server in separate mode: `AUTH_MODE=separate npm run dev`
3. Follow the separate mode testing steps in the main README
## Configuration
The auth server uses the same environment variables as the main server:
The auth server uses the same configuration system as the main server. See [Configuration](../README.md#configuration) in the main README for complete environment variable documentation.
**Auth server specific variables:**
- `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
**This server is for demonstration only.** In production, use established OAuth providers.
For comprehensive security and deployment guidance, see:
- [Security](../README.md#security) - Security measures and best practices
- [Configuration](../README.md#configuration) - Environment setup
- [Monitoring & Debugging](../README.md#monitoring--debugging) - Operational guidance
**Production replacement options:**
- Corporate SSO (Auth0, Okta)
- Cloud providers (AWS Cognito, Azure AD)
- Social providers (Google OAuth, GitHub OAuth)

View file

@ -36,10 +36,10 @@ app.get('/health', (req, res) => {
mode: 'authorization-server',
endpoints: {
metadata: `${AUTH_SERVER_URL}/.well-known/oauth-authorization-server`,
authorize: `${AUTH_SERVER_URL}/oauth/authorize`,
token: `${AUTH_SERVER_URL}/oauth/token`,
register: `${AUTH_SERVER_URL}/oauth/register`,
introspect: `${AUTH_SERVER_URL}/oauth/introspect`
authorize: `${AUTH_SERVER_URL}/authorize`,
token: `${AUTH_SERVER_URL}/token`,
register: `${AUTH_SERVER_URL}/register`,
introspect: `${AUTH_SERVER_URL}/introspect`
}
});
});
@ -60,7 +60,7 @@ app.use(mcpAuthRouter({
}));
// Token introspection endpoint (RFC 7662)
app.post('/oauth/introspect', express.urlencoded({ extended: false }), async (req, res) => {
app.post('/introspect', express.urlencoded({ extended: false }), async (req, res) => {
try {
const { token } = req.body;
@ -127,10 +127,10 @@ app.listen(AUTH_SERVER_PORT, () => {
url: AUTH_SERVER_URL,
endpoints: {
metadata: `${AUTH_SERVER_URL}/.well-known/oauth-authorization-server`,
authorize: `${AUTH_SERVER_URL}/oauth/authorize`,
token: `${AUTH_SERVER_URL}/oauth/token`,
register: `${AUTH_SERVER_URL}/oauth/register`,
introspect: `${AUTH_SERVER_URL}/oauth/introspect`
authorize: `${AUTH_SERVER_URL}/authorize`,
token: `${AUTH_SERVER_URL}/token`,
register: `${AUTH_SERVER_URL}/register`,
introspect: `${AUTH_SERVER_URL}/introspect`
}
});

View file

@ -56,7 +56,7 @@ export class ExternalAuthVerifier implements OAuthTokenVerifier {
try {
// Token introspection is OAuth 2.0 standard (RFC 7662) for validating tokens
// The auth server checks if the token is valid and returns metadata about it
const response = await fetch(`${this.authServerUrl}/oauth/introspect`, {
const response = await fetch(`${this.authServerUrl}/introspect`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `token=${encodeURIComponent(token)}`,