Skip to main content
Glama

Authenticated Next.js MCP Server

PROJECT_DOCUMENTATION.md23.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.

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vedaterenoglu/ve-nextjs-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server