@auth0/auth0-mcp-server
Version:
Auth0 Model Context Protocol (MCP) Server (Beta) — A secure and extendable implementation of an MCP server that provides AI assistants with controlled access to the Auth0 Management API through natural language. This project is in beta and not intended fo
133 lines • 5.46 kB
JavaScript
import { clients } from '../clients/index.js';
import { log, logError } from '../utils/logger.js';
import { requestAuthorization } from '../auth/device-auth-flow.js';
import { requestClientCredentialsAuthorization } from '../auth/client-credentials-flow.js';
import { promptForScopeSelection } from '../utils/terminal.js';
import { getAllScopes } from '../utils/scopes.js';
import { Glob } from '../utils/glob.js';
import chalk from 'chalk';
import trackEvent from '../utils/analytics.js';
/**
* Resolves scope patterns to actual scope values
*
* @param {string[] | undefined} scopePatterns - Scope patterns from command line
* @returns {Promise<string[]>} - The selected scopes
*/
async function resolveScopes(scopePatterns) {
// If no scopes provided, prompt user for selection
if (!scopePatterns?.length) {
return promptForScopeSelection();
}
const allAvailableScopes = getAllScopes();
const matchedScopes = new Set();
const invalidScopes = new Set();
// Match patterns against available scopes
for (const pattern of scopePatterns) {
let foundMatch = false;
const glob = new Glob(pattern);
for (const scope of allAvailableScopes) {
if (glob.matches(scope)) {
matchedScopes.add(scope);
foundMatch = true;
}
}
// Track non-wildcard patterns that didn't match anything
if (!glob.hasWildcards() && !foundMatch) {
invalidScopes.add(pattern);
}
}
// Handle invalid scopes
if (invalidScopes.size > 0) {
const errorMessage = `Error: The following scopes are not valid: ${Array.from(invalidScopes).join(', ')}`;
logError(errorMessage);
logError(chalk.yellow(`Valid scopes are: ${allAvailableScopes.join(', ')}`));
process.exit(1);
}
// Handle matched scopes
const matchedScopesArray = Array.from(matchedScopes);
if (matchedScopesArray.length === 0) {
log(chalk.yellow('No scopes matched the provided patterns, proceeding to scope selection.'));
return promptForScopeSelection();
}
return promptForScopeSelection(matchedScopesArray);
}
/**
* Configures the specified client with options
*
* @param {ClientType} clientType - Type of the client to configure
* @param {InitOptions} options - Configuration options
*/
async function configureClient(clientType, options) {
const manager = clients[clientType];
if (!manager) {
logError(`Invalid client type specified: ${clientType}`);
logError(`Available clients are: ${Object.keys(clients).join(', ')}`);
process.exit(1);
}
log(`Configuring ${manager.displayName} as client...`);
const clientOptions = {
tools: options.tools,
readOnly: options.readOnly,
};
await manager.configure(clientOptions);
}
/**
* Initializes the Auth0 MCP server with the specified client, tools and scopes.
*
* This function orchestrates the complete initialization process by:
* 1. Resolving and validating requested scopes
* 2. Obtaining authorization through the device flow
* 3. Configuring the selected client (Claude, Claude Code, Windsurf, Cursor, VS Code or Gemini CLI)
*
* @param {InitOptions} options - Configuration options including:
* - client: The target client type to configure ('claude', 'claude-code', 'windsurf', 'cursor', 'vscode' or 'gemini')
* - scopes: Optional scope patterns for authorization (will prompt if omitted)
* - tools: Tool patterns to enable (e.g., ['auth0_list_*'])
* - (no-)interaction: Should the CLI prompt the user to press return to open the browser
*
* @returns {Promise<void>} A promise that resolves when initialization is complete
*
* @throws {Error} If authorization fails or client configuration encounters an error
*
* @example
* // Initialize with Claude client and all tools
* await init({ client: 'claude', tools: ['*'] });
*
* @example
* // Initialize with Windsurf client and specific tools
* await init({
* client: 'windsurf',
* tools: ['auth0_list_*', 'auth0_get_*'],
* scopes: ['read:*']
* });
*/
const init = async (options) => {
log('Initializing Auth0 MCP server...');
log(`Configuring server with selected tools: ${options.tools.join(', ')}`);
if (options.readOnly) {
log('Running in read-only mode - only read operations will be available');
}
trackEvent.trackInit(options.client);
// Check if client credentials parameters are provided for Private Cloud authentication
const { auth0Domain, auth0ClientId, auth0ClientSecret } = options;
if (auth0Domain && auth0ClientId && auth0ClientSecret) {
// Client credentials flow for Private Cloud
log('Using client credentials flow for authentication');
await requestClientCredentialsAuthorization({
auth0Domain: auth0Domain,
auth0ClientId: auth0ClientId,
auth0ClientSecret: auth0ClientSecret,
});
}
else {
// Device authorization flow for public cloud
log('Using device authorization flow for authentication');
// Handle scope resolution
const selectedScopes = await resolveScopes(options.scopes);
await requestAuthorization(selectedScopes, options.interaction);
}
// Configure the requested client
await configureClient(options.client, options);
};
export default init;
//# sourceMappingURL=init.js.map