UNPKG

mcp-orchestrator

Version:

MCP Orchestrator - Discover and install MCPs with automatic OAuth support. Uses Claude CLI for OAuth MCPs (Canva, Asana, etc). 34 trusted MCPs from Claude Partners.

120 lines (119 loc) 4.02 kB
/** * OAuth Client Provider for MCP Orchestrator * Handles OAuth 2.1 authentication flow with automatic browser opening */ import { exec } from 'child_process'; const CALLBACK_PORT = 8095; const CALLBACK_URL = `http://localhost:${CALLBACK_PORT}/callback`; /** * In-memory OAuth client provider * Automatically opens browser for authorization */ export class MCPOAuthClientProvider { serverName; onAuthUrlGenerated; storage = {}; constructor(serverName, onAuthUrlGenerated) { this.serverName = serverName; this.onAuthUrlGenerated = onAuthUrlGenerated; } get redirectUrl() { return CALLBACK_URL; } get clientMetadata() { return { client_name: `MCP Orchestrator - ${this.serverName}`, redirect_uris: [CALLBACK_URL], grant_types: ['authorization_code', 'refresh_token'], response_types: ['code'], token_endpoint_auth_method: 'none', // Public client (no secret) scope: 'mcp:tools' }; } clientInformation() { return this.storage.clientInformation; } async saveClientInformation(clientInformation) { this.storage.clientInformation = clientInformation; console.error(`✅ Saved OAuth client information for ${this.serverName}`); } tokens() { return this.storage.tokens; } async saveTokens(tokens) { this.storage.tokens = tokens; console.error(`✅ Saved OAuth tokens for ${this.serverName}`); } async redirectToAuthorization(authorizationUrl) { console.error(`🌐 Opening browser for ${this.serverName} authentication...`); console.error(`📍 Auth URL: ${authorizationUrl.toString()}`); // Notify caller about auth URL if (this.onAuthUrlGenerated) { this.onAuthUrlGenerated(authorizationUrl); } // Open browser automatically await this.openBrowser(authorizationUrl.toString()); } async saveCodeVerifier(codeVerifier) { this.storage.codeVerifier = codeVerifier; } codeVerifier() { if (!this.storage.codeVerifier) { throw new Error('No code verifier saved'); } return this.storage.codeVerifier; } /** * Opens URL in user's default browser * Cross-platform support: Windows, macOS, Linux */ async openBrowser(url) { const platform = process.platform; let command; switch (platform) { case 'darwin': // macOS command = `open "${url}"`; break; case 'win32': // Windows command = `start "" "${url}"`; break; default: // Linux and others command = `xdg-open "${url}"`; break; } return new Promise((resolve, reject) => { exec(command, (error) => { if (error) { console.error(`⚠️ Failed to open browser automatically: ${error.message}`); console.error(`📋 Please manually open: ${url}`); // Don't reject - manual opening is acceptable resolve(); } else { console.error(`✅ Browser opened successfully`); resolve(); } }); }); } /** * Clear all stored credentials */ async invalidateCredentials(scope) { switch (scope) { case 'all': this.storage = {}; break; case 'client': delete this.storage.clientInformation; break; case 'tokens': delete this.storage.tokens; break; case 'verifier': delete this.storage.codeVerifier; break; } console.error(`🗑️ Invalidated ${scope} credentials for ${this.serverName}`); } }