PROJECT_DOCUMENTATION.md•23.4 kB
# MCP Server with Clerk Authentication - Complete Project Documentation
## Table of Contents
1. [Project Overview](#project-overview)
2. [Architecture](#architecture)
3. [Features](#features)
4. [Technology Stack](#technology-stack)
5. [Project Structure](#project-structure)
6. [Authentication System](#authentication-system)
7. [API Endpoints](#api-endpoints)
8. [Setup Instructions](#setup-instructions)
9. [Configuration](#configuration)
10. [Usage Examples](#usage-examples)
11. [Security Features](#security-features)
12. [Troubleshooting](#troubleshooting)
13. [Development Guide](#development-guide)
14. [Deployment](#deployment)
## Project Overview
This is a Next.js-based Model Context Protocol (MCP) server with integrated Clerk authentication and user-specific API key management. The system provides secure access to MCP tools through user-managed API keys, with sign-in only access control.
### Key Capabilities
- **MCP Server**: Provides Next.js documentation search tools via MCP protocol
- **Clerk Authentication**: Secure sign-in only authentication system
- **API Key Management**: User-specific API key creation, management, and revocation
- **Multiple Auth Methods**: Supports user API keys, OAuth 2.1 with PKCE, and bearer tokens
- **Protected Routes**: Dashboard and API management require authentication
- **Responsive UI**: Modern, mobile-friendly interface
## Architecture
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ MCP Client │────│ API Gateway │────│ MCP Server │
│ (AI Agent) │ │ (Authentication)│ │ (Next.js Docs) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
┌─────────────────┐
│ User Dashboard │
│ (API Key Mgmt) │
└─────────────────┘
│
┌─────────────────┐
│ Clerk Auth │
│ (Sign-in Only) │
└─────────────────┘
```
## Features
### Authentication Features
- ✅ **Sign-in only access**: Users cannot self-register
- ✅ **Clerk integration**: Enterprise-grade authentication
- ✅ **Protected routes**: Automatic route protection middleware
- ✅ **Session management**: Secure session handling
- ✅ **User management**: Admin-controlled user addition
### API Key Management Features
- ✅ **User-specific keys**: Each user manages their own API keys
- ✅ **Scoped permissions**: Keys support granular scope-based access
- ✅ **Full CRUD operations**: Create, read, update, delete API keys
- ✅ **Usage tracking**: Last used timestamps and analytics
- ✅ **Secure generation**: Cryptographically secure key generation
- ✅ **Key limits**: Maximum 10 keys per user
### MCP Server Features
- ✅ **Next.js documentation tool**: Search and retrieve Next.js docs
- ✅ **Multiple auth methods**: User keys, OAuth 2.1, bearer tokens
- ✅ **Vercel MCP adapter**: Production-ready MCP implementation
- ✅ **Error handling**: Comprehensive error responses
- ✅ **Rate limiting ready**: Infrastructure for rate limiting
### UI/UX Features
- ✅ **Responsive dashboard**: Modern, mobile-friendly interface
- ✅ **Real-time updates**: Immediate feedback for user actions
- ✅ **Copy to clipboard**: Easy API key copying
- ✅ **Usage instructions**: Built-in examples and documentation
- ✅ **Loading states**: Proper loading indicators
## Technology Stack
### Frontend
- **Next.js 15.3.4**: React framework with App Router
- **React 19**: Latest React with concurrent features
- **TypeScript**: Type-safe development
- **Tailwind CSS**: Utility-first CSS framework
- **Clerk**: Authentication and user management
### Backend
- **Next.js API Routes**: Serverless API endpoints
- **Vercel MCP Adapter**: MCP protocol implementation
- **Zod**: Runtime type validation
- **Node.js Crypto**: Secure key generation
### Development Tools
- **ESLint**: Code linting
- **TypeScript Compiler**: Type checking
- **npm**: Package management
## Project Structure
```
ve-nextjs-mcp-server/
├── src/
│ ├── app/
│ │ ├── api/
│ │ │ ├── [transport]/
│ │ │ │ └── route.ts # Main MCP handler
│ │ │ ├── auth/
│ │ │ │ └── token/
│ │ │ │ └── route.ts # Simple bearer token auth
│ │ │ ├── keys/
│ │ │ │ ├── route.ts # User API key management
│ │ │ │ └── [keyId]/
│ │ │ │ └── route.ts # Individual key operations
│ │ │ └── oauth/
│ │ │ ├── authorize/
│ │ │ │ └── route.ts # OAuth authorization
│ │ │ ├── token/
│ │ │ │ └── route.ts # OAuth token exchange
│ │ │ ├── register/
│ │ │ │ └── route.ts # OAuth client registration
│ │ │ └── .well-known/
│ │ │ └── oauth-authorization-server/
│ │ │ └── route.ts # OAuth metadata
│ │ ├── dashboard/
│ │ │ └── page.tsx # Main user dashboard
│ │ ├── sign-in/
│ │ │ └── [[...sign-in]]/
│ │ │ └── page.tsx # Clerk sign-in page
│ │ ├── sign-up/
│ │ │ └── [[...sign-up]]/
│ │ │ └── page.tsx # Disabled sign-up redirect
│ │ ├── layout.tsx # Root layout with Clerk provider
│ │ ├── page.tsx # Homepage with auth redirect
│ │ └── globals.css # Global styles
│ ├── lib/
│ │ ├── api-keys.ts # Shared API key management
│ │ └── oauth.ts # OAuth 2.1 implementation
│ └── middleware.ts # Route protection middleware
├── examples/
│ ├── oauth-client.js # OAuth client example
│ └── README.md # Authentication examples
├── .env.example # Environment variables template
├── SETUP.md # Setup instructions
├── PROJECT_DOCUMENTATION.md # This file
└── package.json # Dependencies and scripts
```
## Authentication System
### 1. Clerk Authentication
The primary authentication system uses Clerk for secure user management:
- **Sign-in only**: Registration is disabled to prevent unauthorized access
- **Multiple providers**: Email, Google, GitHub, etc.
- **Session management**: Secure JWT-based sessions
- **User metadata**: Store additional user information
### 2. API Key Authentication
Three types of API authentication are supported:
#### User-Specific API Keys (Primary)
- Format: `mcp_[64-character-hex]`
- User-managed through dashboard
- Scoped permissions (mcp:tools, mcp:resources)
- Usage tracking and analytics
#### OAuth 2.1 with PKCE (Advanced)
- Full OAuth 2.1 implementation
- PKCE security for public clients
- Refresh token support
- Standards-compliant (RFC 6749, RFC 7636)
#### Simple Bearer Tokens (Fallback)
- Client credentials flow
- For testing and development
- Fixed client ID/secret pairs
### 3. Authentication Flow
```mermaid
sequenceDiagram
participant User
participant Dashboard
participant API
participant MCP
User->>Dashboard: Sign in via Clerk
Dashboard->>API: Create API key
API->>Dashboard: Return mcp_key
User->>MCP: Request with Bearer mcp_key
MCP->>API: Validate key
API->>MCP: Key valid + user info
MCP->>User: MCP response
```
## API Endpoints
### Public Endpoints
| Method | Endpoint | Description | Authentication |
|--------|----------|-------------|----------------|
| GET | `/` | Homepage | None |
| GET | `/sign-in` | Sign-in page | None |
| POST | `/api/mcp` | MCP server endpoint | API Key required |
### Protected Endpoints (Clerk Auth Required)
| Method | Endpoint | Description | Response |
|--------|----------|-------------|----------|
| GET | `/dashboard` | User dashboard | HTML page |
| GET | `/api/keys` | List user's API keys | JSON array |
| POST | `/api/keys` | Create new API key | JSON object |
| DELETE | `/api/keys/[keyId]` | Revoke API key | JSON success |
| GET | `/api/keys/[keyId]` | Get key details | JSON object |
### OAuth Endpoints
| Method | Endpoint | Description | Spec |
|--------|----------|-------------|------|
| GET | `/api/oauth/authorize` | Authorization endpoint | RFC 6749 |
| POST | `/api/oauth/token` | Token endpoint | RFC 6749 |
| POST | `/api/oauth/register` | Client registration | RFC 7591 |
| GET | `/api/oauth/.well-known/oauth-authorization-server` | Server metadata | RFC 8414 |
### MCP Tools
| Tool Name | Description | Parameters |
|-----------|-------------|------------|
| `get_nextjs_docs` | Search Next.js documentation | `topic` (string) |
## Setup Instructions
### Prerequisites
- Node.js 18+ installed
- A Clerk account (free tier available)
- Git for version control
### 1. Clerk Setup
#### Create a Clerk Application
1. Go to [clerk.com](https://clerk.com) and sign up/sign in
2. Create a new application
3. Choose your preferred authentication providers (Email, Google, etc.)
4. **Important**: Disable sign-ups in your Clerk dashboard:
- Go to User & Authentication → Settings
- Turn OFF "Enable sign up"
- This ensures only you can add users to the system
#### Get Your Clerk Keys
1. In your Clerk dashboard, go to Developers → API Keys
2. Copy the "Publishable key" and "Secret key"
### 2. Environment Configuration
Create a `.env.local` file in your project root:
```env
# Clerk Authentication
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_your_publishable_key_here
CLERK_SECRET_KEY=sk_test_your_secret_key_here
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/dashboard
# MCP Server Authentication
MCP_CLIENT_ID=mcp-client
MCP_CLIENT_SECRET=your-secure-secret-here
# Application
NEXT_PUBLIC_CLERK_DOMAIN=http://localhost:3000
NODE_ENV=development
```
### 3. Add Users to Your System
Since sign-up is disabled, you need to manually add users:
1. Go to your Clerk dashboard
2. Navigate to Users
3. Click "Create user"
4. Add the email addresses of people who should have access
5. They will receive an invitation email
### 4. Install Dependencies
```bash
npm install
```
### 5. Start the Development Server
```bash
npm run dev
```
### 6. Testing the System
#### Test Authentication
1. Visit `http://localhost:3000`
2. Click "Sign In"
3. Sign in with an authorized account
4. You should be redirected to the dashboard
#### Test API Key Generation
1. In the dashboard, click "Create New Key"
2. Enter a name and select scopes
3. Copy the generated API key
#### Test MCP Server Access
```bash
# Test with your API key
curl -X POST http://localhost:3000/api/mcp \
-H "Authorization: Bearer mcp_your_generated_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "get_nextjs_docs",
"arguments": {"topic": "app router"}
},
"id": 1
}'
```
### 7. Production Deployment
#### Clerk Production Setup
1. In Clerk dashboard, add your production domain
2. Update environment variables with production keys
3. Ensure HTTPS is enabled for production
#### Environment Variables for Production
```env
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_your_production_key
CLERK_SECRET_KEY=sk_live_your_production_secret
NEXT_PUBLIC_CLERK_DOMAIN=https://your-domain.com
NODE_ENV=production
```
## Configuration
### Environment Variables
#### Required Variables
```env
# Clerk (Required)
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
# Optional Clerk URLs
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/dashboard
```
#### Optional Variables
```env
# MCP Authentication (fallback)
MCP_CLIENT_ID=mcp-client
MCP_CLIENT_SECRET=your-secure-secret
# Application
NEXT_PUBLIC_CLERK_DOMAIN=http://localhost:3000
NODE_ENV=development
```
### Clerk Configuration
#### Authentication Settings
- **Enable sign up**: ❌ Disabled for security
- **Email verification**: ✅ Recommended
- **Password requirements**: Configure as needed
- **Session lifetime**: Default (7 days)
#### User Management
- **Manual user addition**: Through Clerk dashboard only
- **User roles**: Not implemented (all users have same access)
- **User metadata**: Can be extended for additional features
## Usage Examples
### 1. Simple API Key Authentication
```bash
# Get API key from dashboard first
curl -X POST http://localhost:3000/api/mcp \
-H "Authorization: Bearer mcp_abc123..." \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/list",
"id": 1
}'
```
### 2. OAuth 2.1 Flow
```javascript
import { PKCEClient } from './examples/oauth-client.js';
const client = new PKCEClient({
clientId: 'mcp-client',
redirectUri: 'http://localhost:3000/auth/callback',
scope: 'mcp:tools mcp:resources'
});
// Get authorization URL
const authUrl = client.getAuthorizationUrl('state-value');
console.log('Visit:', authUrl);
// After user authorizes, exchange code for tokens
const tokens = await client.exchangeCodeForTokens(authorizationCode);
// Make authenticated requests
const response = await client.makeAuthenticatedRequest('/api/mcp', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: 'tools/call',
params: {
name: 'get_nextjs_docs',
arguments: { topic: 'middleware' }
},
id: 1
})
});
```
### 3. JavaScript MCP Client
```javascript
class MCPClient {
constructor(apiKey, baseUrl = 'http://localhost:3000') {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
}
async callTool(name, arguments = {}) {
const response = await fetch(`${this.baseUrl}/api/mcp`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
jsonrpc: '2.0',
method: 'tools/call',
params: { name, arguments },
id: Date.now()
})
});
return response.json();
}
async listTools() {
const response = await fetch(`${this.baseUrl}/api/mcp`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
jsonrpc: '2.0',
method: 'tools/list',
id: Date.now()
})
});
return response.json();
}
}
// Usage
const client = new MCPClient('mcp_your_api_key_here');
const result = await client.callTool('get_nextjs_docs', {
topic: 'app router'
});
```
## Security Features
### Authentication Security
- ✅ **Sign-in only access**: No public registration
- ✅ **Admin-controlled users**: Manual user addition only
- ✅ **Session security**: Clerk's enterprise-grade session management
- ✅ **HTTPS enforcement**: Required for production
- ✅ **CSRF protection**: Built-in with Clerk
### API Key Security
- ✅ **Cryptographically secure**: Uses Node.js crypto.randomBytes
- ✅ **User isolation**: Users can only access their own keys
- ✅ **Scoped permissions**: Granular access control
- ✅ **Revocation support**: Immediate key invalidation
- ✅ **Usage tracking**: Monitor key usage patterns
### OAuth Security
- ✅ **PKCE protection**: SHA256-based code challenge/verifier
- ✅ **State parameter**: CSRF protection for OAuth flows
- ✅ **Secure redirect URIs**: Whitelist-based validation
- ✅ **Token expiration**: Short-lived access tokens
- ✅ **Refresh token rotation**: Enhanced security for long-lived access
### Infrastructure Security
- ✅ **Environment isolation**: Separate dev/prod configurations
- ✅ **Secrets management**: Environment variable based secrets
- ✅ **Route protection**: Middleware-based authentication
- ✅ **Input validation**: Zod schema validation
- ✅ **Error handling**: Secure error responses
## Troubleshooting
### Common Issues
#### "Unauthorized" errors
**Symptoms**: 401 Unauthorized responses from API endpoints
**Solutions**:
- Check that your Clerk keys are correctly set in `.env.local`
- Ensure the user is signed in to access protected routes
- Verify the API key is valid and not revoked
- Check API key format: `Bearer mcp_...`
#### Sign-up not working
**Symptoms**: Users cannot create accounts
**Solution**: This is intentional! Sign-up is disabled for security. Add users manually through the Clerk dashboard.
#### MCP server not responding
**Symptoms**: No response or errors from MCP endpoints
**Solutions**:
- Check that the API key is included in the Authorization header
- Verify the API key format: `Authorization: Bearer mcp_...`
- Check server logs for detailed error messages
- Ensure the user has the required scopes for the requested operation
#### Environment variable issues
**Symptoms**: Authentication not working, redirects failing
**Solutions**:
- Verify all required environment variables are set
- Check for typos in variable names
- Ensure `.env.local` is in the project root
- Restart the development server after changing environment variables
### Debug Mode
Enable verbose logging for debugging:
```env
# Add to .env.local
DEBUG=mcp:*
NODE_ENV=development
```
### Common Error Codes
| Code | Message | Cause | Solution |
|------|---------|-------|----------|
| 401 | Unauthorized | Missing/invalid API key | Check Authorization header |
| 403 | Forbidden | Insufficient scopes | Verify key has required scopes |
| 404 | Not Found | Invalid endpoint/key ID | Check URL and key existence |
| 429 | Too Many Requests | Rate limit exceeded | Implement backoff strategy |
| 500 | Internal Server Error | Server-side error | Check server logs |
## Development Guide
### Adding New MCP Tools
1. **Define the tool in the MCP handler**:
```typescript
// src/app/api/[transport]/route.ts
server.tool(
'your_new_tool',
'Description of your tool',
{
param1: z.string().describe('Parameter description'),
param2: z.number().optional().describe('Optional parameter')
},
async ({ param1, param2 }) => {
// Your tool implementation
return {
content: [
{
type: 'text',
text: `Result: ${param1}, ${param2}`
}
]
};
}
);
```
2. **Add scope requirements if needed**:
```typescript
// Check user scopes in tool handler
const userKeyResult = validateUserApiKey(token);
if (!userKeyResult.scopes?.includes('your:scope')) {
throw new Error('Insufficient permissions');
}
```
### Adding New Authentication Methods
1. **Create new validation function**:
```typescript
// src/lib/auth-methods.ts
export function validateCustomToken(token: string) {
// Your custom validation logic
return { valid: boolean, userId?: string, scopes?: string[] };
}
```
2. **Add to verification chain**:
```typescript
// src/app/api/[transport]/route.ts
async function verifyToken(token: string) {
// Add your method to the chain
const customResult = validateCustomToken(token);
if (customResult.valid) return true;
// ... existing methods
}
```
### Database Integration
For production use, replace in-memory storage with a database:
1. **Install database client** (e.g., Prisma, Drizzle):
```bash
npm install prisma @prisma/client
```
2. **Update storage functions**:
```typescript
// src/lib/api-keys.ts
import { prisma } from './prisma';
export async function getUserApiKeys(userId: string) {
return prisma.apiKey.findMany({
where: { userId }
});
}
```
### Adding Rate Limiting
Implement rate limiting for API endpoints:
```typescript
// src/lib/rate-limit.ts
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, "10 s"),
});
export async function rateLimitCheck(identifier: string) {
const { success } = await ratelimit.limit(identifier);
return success;
}
```
## Deployment
### Production Environment Setup
#### Clerk Production Configuration
1. **Add production domain** to your Clerk application
2. **Update environment variables** with production keys:
```env
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_your_production_key
CLERK_SECRET_KEY=sk_live_your_production_secret
NEXT_PUBLIC_CLERK_DOMAIN=https://your-domain.com
NODE_ENV=production
```
#### Security Checklist
- ✅ HTTPS enabled and enforced
- ✅ Environment variables secured
- ✅ Database backups configured
- ✅ Monitoring and alerting set up
- ✅ Rate limiting implemented
- ✅ Security headers configured
### Deployment Platforms
#### Vercel (Recommended)
1. **Connect repository** to Vercel
2. **Configure environment variables** in Vercel dashboard
3. **Set build settings**:
- Build Command: `npm run build`
- Output Directory: `.next`
4. **Deploy**
#### Docker Deployment
```dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
```
#### Traditional Server
```bash
# Build the application
npm run build
# Start production server
npm start
# Or use PM2 for process management
npm install -g pm2
pm2 start npm --name "mcp-server" -- start
```
### Monitoring and Analytics
Recommended monitoring setup:
- **Application monitoring**: Vercel Analytics, DataDog, New Relic
- **Error tracking**: Sentry, Bugsnag
- **Uptime monitoring**: Pingdom, UptimeRobot
- **Log aggregation**: LogDrain, Papertrail
- **Performance monitoring**: Lighthouse CI, SpeedCurve
### Scaling Considerations
For high-traffic deployments:
1. **Database optimization**: Use connection pooling, read replicas
2. **Caching**: Implement Redis for session and API key caching
3. **CDN**: Use Cloudflare or similar for static assets
4. **Load balancing**: Multiple server instances with load balancer
5. **Rate limiting**: Implement per-user and global rate limits
---
This project provides a complete, production-ready MCP server with authentication. For questions or issues, refer to the [MCP documentation](https://modelcontextprotocol.io/docs) or create an issue in the project repository.