The "Rails for MCP OAuth" - Build OAuth-enabled MCP servers in minutes, not hours.
Transform 200+ lines of OAuth boilerplate into 20 lines of clean, production-ready code.
npm install @sg20/mcp-oauth-frameworkCreate a GitHub MCP Server:
import { BaseMCPServer } from '@sg20/mcp-oauth-framework/base';
class GitHubServer extends BaseMCPServer {
constructor() {
super({
name: 'github-server',
version: '1.0.0',
providers: [{
name: 'github',
clientId: process.env.GITHUB_CLIENT_ID!,
authorizationUrl: 'https://github.com/login/oauth/authorize',
tokenUrl: 'https://github.com/login/oauth/access_token',
scope: ['repo', 'user:email']
}]
});
}
async initialize() {
this.addTool({
name: 'list-repos',
description: 'List user repositories',
auth: { required: true, provider: 'github' },
handler: async () => {
const response = await this.makeAuthenticatedRequest(
'github',
'https://api.github.com/user/repos'
);
return response.json();
}
});
}
}
new GitHubServer().start();That's it! You now have a fully functional OAuth-enabled MCP server with:
- โ Secure PKCE OAuth 2.0 flow
- โ Automatic token management
- โ Browser-based authentication
- โ Production-ready error handling
// 200+ lines of OAuth boilerplate:
// - PKCE implementation
// - Token storage & encryption
// - Browser flow management
// - Token refresh logic
// - Error handling
// - Security validation
// - MCP integration
// ... and much more// 20 lines of clean code:
class MyServer extends BaseMCPServer {
constructor() {
super({ providers: [oauthProvider] });
}
async initialize() {
this.addTool(/* your tool */);
}
}Result: 90% less code, 100% more reliability
See our complete GitHub server example that demonstrates:
- 15 GitHub API tools - repos, issues, PRs, files, search
- Production-ready - full error handling, validation, logging
- 2-minute setup - simple
.envconfiguration - Real OAuth flow - works with Claude Desktop out of the box
User: "List my GitHub repositories"
What happens:
- ๐ Browser opens to GitHub OAuth page
- โ User clicks "Authorize"
- ๐ Tokens stored securely locally
- ๐ Repository list appears in Claude
- ๐ Next time: instant results (no browser needed)
@sg20/mcp-oauth-framework/
โโโ base # MCP server foundation
โ โโโ BaseMCPServer # Abstract base class
โ โโโ ToolRegistry # Tool management with auth
โโโ auth # OAuth implementation
โ โโโ AuthManager # Authentication orchestrator
โ โโโ OAuthFlow # PKCE browser flow
โ โโโ TokenStore # Secure token storage
โโโ shared # Common utilities
โโโ types # TypeScript interfaces
โโโ utils # OAuth helpers & validation
- ๐ PKCE Flow - Proof Key for Code Exchange prevents code interception
- ๐ Encrypted Storage - Tokens encrypted with machine-specific keys
- ๐ Auto Refresh - Expired tokens refreshed automatically
- โ Scope Validation - Tools validate required OAuth permissions
- ๐ก๏ธ Secure Defaults - Minimal permissions, safe storage locations
The foundation for all OAuth-enabled MCP servers:
class MyServer extends BaseMCPServer {
constructor(options: BaseMCPServerOptions) {
super(options);
}
// Required: Implement your server initialization
async initialize(): Promise<void> {
this.addTool({
name: 'my-tool',
description: 'My awesome tool',
auth: { required: true, provider: 'github', scopes: ['repo'] },
handler: async (params, context) => {
// context.auth contains authenticated user info
return await this.makeAuthenticatedRequest('github', '/api/endpoint');
}
});
}
// Required: Cleanup on shutdown
async cleanup(): Promise<void> {
// Your cleanup logic
}
}// Tool registration
protected addTool(definition: ToolDefinition): void
// Authenticated API requests
protected makeAuthenticatedRequest(
provider: string,
url: string,
options?: RequestInit,
requiredScopes?: string[]
): Promise<Response>
// Manual authentication
protected requireAuth(provider: string, scopes?: string[]): Promise<AuthenticatedRequest>
// Logging
protected log(message: string, level?: 'info' | 'warn' | 'error'): voidinterface OAuthProvider {
name: string; // Unique identifier (e.g., 'github')
clientId: string; // OAuth client ID
clientSecret?: string; // OAuth client secret (optional with PKCE)
authorizationUrl: string; // Authorization endpoint
tokenUrl: string; // Token exchange endpoint
scope: string[]; // Required OAuth scopes
additionalParams?: Record<string, string>; // Extra parameters
}interface ToolDefinition {
name: string; // Tool name (kebab-case)
description: string; // Tool description for users
auth?: { // Authentication requirements
required: boolean;
provider?: string; // OAuth provider name
scopes?: string[]; // Required scopes
message?: string; // Custom auth prompt
};
handler: (params: any, context: RequestContext) => Promise<any>;
}- GitHub - Repositories, issues, pull requests, files
- Google - Drive, Gmail, Calendar APIs
- Microsoft - Office 365, OneDrive, Teams
- Custom - Easy to add any OAuth 2.0 provider
const customProvider: OAuthProvider = {
name: 'my-service',
clientId: process.env.MY_SERVICE_CLIENT_ID!,
authorizationUrl: 'https://myservice.com/oauth/authorize',
tokenUrl: 'https://myservice.com/oauth/token',
scope: ['read', 'write'],
additionalParams: {
audience: 'https://myservice.com/api'
}
};Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/path/to/your/server/dist/index.js"]
}
}
}That's it! The server automatically:
- โ
Reads configuration from
.envfile - โ Validates OAuth credentials
- โ Provides helpful error messages
- โ Handles authentication flow
Create .env in your server directory:
# Required
GITHUB_CLIENT_ID=your_github_client_id
# Optional but recommended
GITHUB_CLIENT_SECRET=your_github_client_secret
# Optional: Enable debug logging
DEBUG=falseThe fastest way to understand the framework:
git clone https://github.com/swayamg20/mcp-framework.git
cd mcp-framework/examples/github-server
# Follow the 2-minute setup guide
cat SIMPLE-SETUP.mdmkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @sg20/mcp-oauth-framework dotenv
# Create your server (see API examples above)
# Add to Claude Desktop config
# Start building amazing OAuth tools!- GitHub Issues - Bug reports and feature requests
- Discussions - Share your servers and get help
- Examples - Browse community-built servers
- Contributing - Help improve the framework
class MultiServiceServer extends BaseMCPServer {
constructor() {
super({
name: 'multi-service-server',
version: '1.0.0',
providers: [
githubProvider,
googleProvider,
slackProvider
]
});
}
}this.addTool({
name: 'advanced-tool',
description: 'Tool with custom logic',
auth: { required: true, provider: 'github', scopes: ['repo'] },
handler: async (params, context) => {
// Access authenticated user info
const { tokens, user } = context.auth!;
// Custom validation
if (!user.email?.endsWith('@company.com')) {
throw new Error('Only company users allowed');
}
// Make multiple authenticated requests
const [repos, issues] = await Promise.all([
this.makeAuthenticatedRequest('github', '/user/repos'),
this.makeAuthenticatedRequest('github', '/issues')
]);
return { repos: await repos.json(), issues: await issues.json() };
}
});try {
const result = await this.makeAuthenticatedRequest('github', '/user/repos');
return result.json();
} catch (error) {
if (error.code === 'AUTHENTICATION_REQUIRED') {
// User needs to re-authenticate
throw new Error('Please re-authenticate with GitHub');
}
if (error.code === 'INSUFFICIENT_SCOPE') {
// User needs more permissions
throw new Error('Additional GitHub permissions required');
}
// Handle other errors
throw error;
}# Required
GITHUB_CLIENT_ID=your_production_client_id
# Recommended for production
GITHUB_CLIENT_SECRET=your_production_client_secret
# Optional configuration
DEBUG=false
OAUTH_PORT=8080
OAUTH_HOST=localhost
OAUTH_CALLBACK_PATH=/oauth/callback- โ Use HTTPS in production - Configure proper callback URLs
- โ Validate all inputs - Framework provides validation helpers
- โ Monitor token usage - Implement logging and monitoring
- โ Regular security updates - Keep dependencies updated
- โ Never commit secrets - Always use environment variables
- ๐ Token reuse - Framework automatically caches valid tokens
- ๐ Concurrent requests - Use
Promise.all()for parallel API calls - ๐ Scope optimization - Request only necessary permissions
- ๐ Error recovery - Implement retry logic for transient failures
- GitHub Server Example - Production-ready implementation
- Simple Setup Guide - 2-minute setup
- Usage Guide - Comprehensive tutorial
We welcome contributions! Here's how to get started:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes with tests and documentation
- Submit a pull request
git clone https://github.com/swayamg20/mcp-framework.git
cd mcp-framework
npm install
npm run build
npm test- Add provider configuration to types
- Implement user info normalization
- Add example usage
- Update documentation
- Submit PR with tests
- ๐๏ธ Architecture: Modular, extensible, type-safe
- ๐ Security: PKCE, encrypted storage, scope validation
- ๐ Code Reduction: 90% less OAuth boilerplate
- โก Performance: Automatic token caching and refresh
- ๐งช Testing: Comprehensive test suite
- ๐ Documentation: Complete API reference and examples
MIT License - see LICENSE file for details.
- ๐ Bug Reports: GitHub Issues
- ๐ฌ Discussions: GitHub Discussions
- ๐ Documentation: Complete guides and API reference included
- ๐ก Feature Requests: Submit ideas via GitHub Issues
Ready to build OAuth-enabled MCP servers in minutes instead of hours?
Made with โค๏ธ for the MCP community. Empowering developers to build amazing AI integrations.