UNPKG

okta-mcp-server

Version:

Model Context Protocol (MCP) server for Okta API operations with support for bulk operations and caching

142 lines 4.75 kB
import { z } from 'zod'; import fs from 'fs'; import path from 'path'; // Load environment variables manually to avoid dotenv stdout pollution // This prevents the "[dotenv@17.2.1] injecting env..." message function loadEnvFile() { try { const envPath = path.resolve(process.cwd(), '.env'); if (fs.existsSync(envPath)) { const envContent = fs.readFileSync(envPath, 'utf8'); const lines = envContent.split('\n'); for (const line of lines) { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith('#')) continue; const [key, ...valueParts] = trimmed.split('='); if (key && valueParts.length > 0) { const value = valueParts.join('=').replace(/^["']|["']$/g, ''); if (!process.env[key]) { process.env[key] = value; } } } } } catch (error) { // Silently ignore .env file errors } } // Load environment variables without dotenv's stdout pollution loadEnvFile(); // Environment variable schema - SIMPLIFIED const EnvSchema = z.object({ // Mock mode configuration USE_MOCK_OKTA: z .union([z.string(), z.boolean()]) .optional() .transform((v) => { if (typeof v === 'boolean') return v; return v === 'true'; }) .default(false), // Okta configuration - SIMPLIFIED to just domain and API token OKTA_DOMAIN: z.string().optional(), OKTA_API_TOKEN: z.string().optional(), // Optional MCP OAuth protection MCP_AUTH_REQUIRED: z .string() .transform((v) => v === 'true') .optional() .default('false'), MCP_AUTH_AUDIENCE: z.string().optional(), MCP_AUTH_ISSUER: z.string().optional(), // Read-only mode - prevents dangerous write operations READ_ONLY_MODE: z .string() .transform((v) => v === 'true') .optional() .default('false'), // Server configuration NODE_ENV: z.enum(['development', 'production', 'test']).default('development'), LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'), // Cache configuration - kept for performance CACHE_ENABLED: z .string() .transform((v) => v === 'true') .default('true'), CACHE_TYPE: z.enum(['memory', 'sqlite']).default('memory'), CACHE_TTL: z .string() .transform((v) => parseInt(v, 10)) .default('300'), CACHE_MAX_SIZE: z .string() .transform((v) => parseInt(v, 10)) .default('1000'), // Rate limiting - kept for Okta API compliance RATE_LIMIT_MAX: z .string() .transform((v) => parseInt(v, 10)) .default('100'), RATE_LIMIT_WINDOW: z .string() .transform((v) => parseInt(v, 10)) .default('60000'), }); // Parse environment variables const env = EnvSchema.parse(process.env); // Load and validate configuration export function loadConfig() { // Skip validation if using mock mode if (!env.USE_MOCK_OKTA) { // Validate that we have API token if (!env.OKTA_API_TOKEN) { throw new Error('OKTA_API_TOKEN must be provided'); } if (!env.OKTA_DOMAIN) { throw new Error('OKTA_DOMAIN must be provided when USE_MOCK_OKTA is false'); } } const config = { name: 'okta-mcp-server', version: '2.0.0', // Major version bump for breaking changes okta: { domain: env.OKTA_DOMAIN || 'https://mock.okta.com', apiToken: env.OKTA_API_TOKEN || '', requestTimeout: 30000, maxRetries: 3, rateLimitPerMinute: env.RATE_LIMIT_MAX, }, // Optional MCP OAuth protection auth: env.MCP_AUTH_REQUIRED ? { required: true, audience: env.MCP_AUTH_AUDIENCE, issuer: env.MCP_AUTH_ISSUER, } : undefined, cache: { enabled: env.CACHE_ENABLED, type: env.CACHE_TYPE, ttl: env.CACHE_TTL, maxSize: env.CACHE_MAX_SIZE, }, logging: { level: env.LOG_LEVEL, format: env.NODE_ENV === 'production' ? 'json' : 'pretty', }, features: { streaming: true, caching: env.CACHE_ENABLED, rateLimit: true, audit: true, readOnlyMode: env.READ_ONLY_MODE, }, }; return config; } // Export parsed environment for direct access if needed export { env }; //# sourceMappingURL=index.js.map