xtfocus/mcp-server-ts-study
If you are the rightful owner of mcp-server-ts-study and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
This document provides a comprehensive overview of setting up and running a Model Context Protocol (MCP) server using Next.js and the mcp-handler package.
GitHub OAuth MCP Server
OAuth Proxy Pattern with Dynamic Client Registration
This MCP server implements GitHub OAuth authentication using the OAuth Proxy Pattern, which enables Dynamic Client Registration (DCR) while maintaining compatibility with GitHub OAuth. The server acts as an OAuth authorization server for MCP clients and proxies authentication requests to GitHub.
Features
- 🔐 GitHub OAuth Authentication: Secure access using GitHub OAuth
- 🛠️ Multiple Tools: Echo, dice rolling, admin info, and GitHub user info
- 🔒 Scope-based Access Control: Minimal scopes (
read:user) for security - 📋 OAuth Metadata Endpoints: Full OAuth 2.1 discovery compliance
- 🚀 Dynamic Client Registration: Automatic client registration (RFC7591)
- 🛡️ OAuth Proxy Pattern: Enables DCR with GitHub OAuth
- 🌐 Web Login Interface: Simple login page at
localhost:3000 - 📡 Real-time Notifications: Server-Sent Events (SSE) for progress updates
- 🎯 Progress Tracking: Step-based and phase-based progress notifications
- 🧪 Comprehensive Testing: 49 unit tests + integration test scripts
Available Tools
- echo - Echo a message with user context (requires
read:user) - roll_dice - Roll one or more dice with progress notifications (requires
read:user) - wait - Configurable wait with progress updates (requires
read:user) - generic_notifier_demo - Demonstrate generic notification capabilities (requires
read:user) - adminInfo - Get admin information (requires
read:user) - githubUserInfo - Get information about the authenticated GitHub user (requires
read:user)
How It Works
OAuth Proxy Pattern
The server implements an OAuth Proxy Pattern that solves the fundamental incompatibility between GitHub OAuth (no DCR support) and MCP requirements (DCR required):
- MCP Client Registration: Clients register dynamically via
/api/oauth/register - Authorization Request: Clients request authorization via
/oauth/authorize - GitHub OAuth: Server redirects to GitHub using our OAuth App credentials
- Token Exchange: Server exchanges GitHub codes for our own tokens
- MCP Access: Clients use our tokens to access MCP tools
Security Features
- Minimal Scopes: Always requests only
read:userfrom GitHub - Scope Filtering: Ignores client-requested scopes for security
- PKCE Support: Handles PKCE at our layer, not GitHub's
- Token Expiration: 1-hour expiration for access tokens
- Client Validation: Strict client credential validation
GitHub OAuth Setup
1. Create a GitHub OAuth App
- Go to GitHub Developer Settings
- Click "New OAuth App"
- Fill in the details:
- Application name:
MCP Server(or any name you prefer) - Homepage URL:
http://localhost:3000(for development) - Authorization callback URL:
http://localhost:3000/api/oauth/callback
- Application name:
- Note down the Client ID and Client Secret
2. Configure Environment Variables
Create .env.local and add the following:
# GitHub OAuth Configuration (for our OAuth proxy)
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
Important: These are the credentials for our GitHub OAuth App that acts as the proxy. MCP clients will register dynamically and get their own credentials.
Usage
Running the Server
npm install
npm run dev
The server will be available at http://localhost:3000.
Web Login Interface
Visit http://localhost:3000 to see a simple login interface that demonstrates the OAuth flow.
Testing with MCP Inspector
- Start the server:
npm run dev - Open MCP Inspector in your browser
- Connect to:
http://localhost:3000/mcp - Follow the OAuth flow - the Inspector will automatically:
- Register as a client
- Request authorization
- Complete GitHub OAuth
- Access MCP tools
No manual token configuration needed! The OAuth flow handles everything automatically.
Testing with Cursor
Add the following to your Cursor MCP configuration:
{
"mcpServers": {
"github-mcp": {
"command": "npx",
"args": ["mcp-remote", "http://localhost:3000/mcp"],
"env": {}
}
}
}
Note: Cursor will automatically handle the OAuth flow when you first connect.
OAuth Discovery and Dynamic Client Registration
The server implements complete OAuth 2.1 discovery and Dynamic Client Registration (DCR) according to the MCP specification:
OAuth Discovery Endpoints:
/.well-known/oauth-protected-resource- Protected resource metadata/.well-known/oauth-authorization-server- Authorization server metadata/.well-known/openid-configuration- OpenID Connect metadata
Dynamic Client Registration:
POST /api/oauth/register- Client registration endpoint (RFC7591)- Automatically generates client credentials for MCP clients
- No manual registration required
- Supports automatic client discovery and registration
OAuth Endpoints:
GET /oauth/authorize- Authorization endpointPOST /api/oauth/token- Token exchange endpointGET /api/oauth/userinfo- User information endpoint
What This Enables:
- Seamless client registration - MCP clients can automatically register
- No manual configuration - No need to pre-register clients
- Standards compliance - Follows OAuth 2.1 and RFC7591 specifications
- Automatic discovery - Clients can discover all required endpoints
- GitHub OAuth compatibility - Works with GitHub's OAuth system
Deployment
Vercel Deployment
- Push your code to GitHub
- Connect your repository to Vercel
- Set the environment variables in Vercel dashboard:
GITHUB_CLIENT_IDGITHUB_CLIENT_SECRET
- Deploy
Environment Variables for Production
Update your GitHub OAuth App for production:
- Authorization callback URL:
https://your-app.vercel.app/api/oauth/callback
Production Considerations
For production deployment, you'll need to:
- Replace file-based storage with a database
- Set up monitoring and error tracking
- Configure proper security headers
- Set up automated backups
See CONSIDERATION.md for detailed production deployment guide.
Security Notes
- Never commit your
.env.localfile to version control - Use environment variables for all sensitive configuration
- The server always requests minimal scopes (
read:user) from GitHub - Client-requested scopes are filtered for security
- Access tokens expire after 1 hour
- Authorization codes expire after 10 minutes
Troubleshooting
Common Issues
- "The redirect_uri is not associated with this application": Update your GitHub OAuth App callback URL to
http://localhost:3000/api/oauth/callback - "No code found: server_error, Invalid client": Restart the server to reload client storage
- "GitHub token exchange failed: 400": Check that your GitHub OAuth App credentials are correct
- Broad scopes displayed by GitHub: Revoke existing authorization for your OAuth App in GitHub Settings > Applications
Debug Endpoints
In development, you can access debug endpoints:
GET /api/debug/clients- List registered clientsGET /api/debug/auth-codes?code=xxx- Check authorization codes
Storage
The server uses file-based storage (.oauth-storage.json) for development. This file persists OAuth data between server restarts.
See COMMON_ISSUES.md for detailed troubleshooting guide.
Local Development
Running the Server
npm install
npm run dev
The server will be available at http://localhost:3000.
Testing with MCP Inspector
To test this MCP server using the MCP Inspector:
- Start the server:
npm run dev - Open MCP Inspector in your browser
- Connect to:
http://localhost:3000/mcp - Follow the OAuth flow - no manual configuration needed
Note: The /mcp endpoint uses HTTP transport which works without additional dependencies.
Testing
The project includes comprehensive testing for both integration scenarios and unit tests for the notification system.
Unit Tests
The notification system includes a complete test suite with 49 tests covering all core functionality:
# Run all unit tests
npm test
# Run tests with verbose output
npx jest --verbose
# Run specific test file
npx jest lib/notifications/__tests__/base-notifier.test.ts
# Run tests with coverage report
npx jest --coverage
Test Coverage
- BaseNotificationHandler (19 tests): Core notification functionality, state management, error handling
- ProgressTracker (19 tests): Step-based progress tracking, history management, inheritance
- Configuration (11 tests): Logging system, configuration management, default values
Test Results
✓ Test Suites: 3 passed, 3 total
✓ Tests: 49 passed, 49 total
✓ Time: ~1.6s
Integration Test Scripts
The project includes several test scripts for different scenarios:
# Test basic OAuth functionality
node scripts/test-oauth.mjs
# Test complete OAuth proxy flow
node scripts/test-complete-flow.mjs
# Test web login flow
node scripts/test-web-login.mjs
# Test scope filtering
node scripts/test-scope-filtering.mjs
# Test notification system
node scripts/test-notifications.mjs
# Test MCP client functionality
node scripts/test-client.mjs
# Test streamable HTTP client
node scripts/test-streamable-http-client.mjs
Notification System
The server includes a comprehensive notification system that enables real-time progress updates via Server-Sent Events (SSE). This system is designed to be:
- Generic: No assumptions about task nature - developers can emit any type of notification
- Extensible: Specialized classes for step-based and phase-based progress tracking
- Well-tested: 49 unit tests covering all functionality
- Production-ready: Comprehensive error handling and logging
Key Components
- BaseNotificationHandler: Generic notification interface for any task type
- ProgressTracker: Step-based progress tracking with history
- HierarchicalProgressTracker: Phase-based progress with weighted completion
- NotificationService: Centralized service for creating handlers and sending notifications
- Simplified Decorators: Easy-to-use decorators for tool integration
Usage Examples
// Generic notifications (no task assumptions)
import { withNotifications } from '@/lib/mcp/simplified-decorators';
export const myTool = {
handler: withNotifications(async (notifier, args) => {
if (notifier) {
await notifier.notify("Starting process", { step: 1 });
// ... do work ...
await notifier.complete("All done!");
}
})
};
// Step-based progress tracking
import { withProgressTracking } from '@/lib/mcp/simplified-decorators';
export const myTool = {
handler: withProgressTracking(async (tracker, args) => {
if (tracker) {
await tracker.setTotal(5);
for (let i = 0; i < 5; i++) {
await tracker.updateProgress(`Step ${i + 1}`);
// ... do work ...
}
}
})
};
For detailed documentation, see lib/notifications/README.md and lib/notifications/ARCHITECTURE.md.
Architecture Documentation
ARCHITECTURE.md- Detailed architecture and security featuresCOMMON_ISSUES.md- Issues encountered and solutions implementedCONSIDERATION.md- Production deployment requirements and considerationslib/notifications/README.md- Notification system documentationlib/notifications/ARCHITECTURE.md- Notification system architecture