UNPKG

okta-mcp-server

Version:

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

136 lines 4.5 kB
/** * Read-Only Mode Middleware * * Prevents dangerous write operations when READ_ONLY_MODE is enabled. * This is crucial for production environments where data modification * should be restricted. */ import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; import { protocolSafeLogger as logger } from '../../utils/protocol-safe-logger.js'; // Define write operations that should be blocked in read-only mode const WRITE_OPERATIONS = new Set([ // User operations 'createUser', 'updateUser', 'deleteUser', // Group operations 'createGroup', 'updateGroup', 'deleteGroup', 'addGroupMember', 'removeGroupMember', // Application operations 'createApp', 'updateApp', 'deleteApp', 'activateApp', 'deactivateApp', 'assignUserToApp', 'assignGroupToApp', 'removeUserFromApp', 'removeGroupFromApp', 'updateAppUser', // Policy operations 'createPasswordPolicy', 'createSignOnPolicy', 'createMfaPolicy', 'updatePolicy', 'deletePolicy', 'activatePolicy', 'deactivatePolicy', 'createPolicyRule', 'updatePolicyRule', 'deletePolicyRule', 'activatePolicyRule', 'deactivatePolicyRule', // Bulk operations 'bulkCreateUsers', 'bulkUpdateUsers', 'bulkDeleteUsers', ]); // Define read-only operations that are allowed const READ_OPERATIONS = new Set([ // User operations 'listUsers', 'getUser', 'getUserGroups', // Group operations 'listGroups', 'getGroup', 'listGroupMembers', // Application operations 'listApps', 'getApp', 'listAppUsers', 'listAppGroups', // Policy operations 'listPolicies', 'getPolicy', 'listPolicyRules', 'getPolicyRule', // Audit operations (all are read-only) 'queryAuditLogs', 'getAuditStatistics', 'exportAuditLogs', 'checkAuditIntegrity', 'generateComplianceReport', 'getAuditMetrics', // Export operations (read-only) 'exportUsers', 'generateImportTemplate', 'getBulkOperationStatus', ]); export class ReadOnlyMiddleware { readOnlyMode; constructor(config) { this.readOnlyMode = config.features?.readOnlyMode ?? false; if (this.readOnlyMode) { logger.warn('🔒 READ-ONLY MODE ENABLED: Write operations are disabled for safety'); } } /** * Check if an operation is allowed in read-only mode */ checkOperation(toolName) { if (!this.readOnlyMode) { return; // Not in read-only mode, allow all operations } // Check if this is a write operation if (WRITE_OPERATIONS.has(toolName)) { logger.error(`🚫 Blocked write operation in read-only mode: ${toolName}`); throw new McpError(ErrorCode.InvalidRequest, `Write operation '${toolName}' is not allowed in read-only mode. ` + `This server is configured for read-only access to prevent accidental data modification. ` + `To enable write operations, set READ_ONLY_MODE=false in your environment variables.`); } // Verify it's a known read operation if (!READ_OPERATIONS.has(toolName)) { logger.warn(`⚠️ Unknown operation in read-only mode: ${toolName}`); // Allow unknown operations by default, but log them } logger.debug(`✅ Allowed read operation: ${toolName}`); } /** * Get information about read-only mode status */ getStatus() { return { readOnlyMode: this.readOnlyMode, allowedOperations: Array.from(READ_OPERATIONS).sort(), blockedOperations: Array.from(WRITE_OPERATIONS).sort(), }; } /** * Get a user-friendly message about read-only mode */ getReadOnlyMessage() { if (!this.readOnlyMode) { return 'Read-only mode is disabled. All operations are allowed.'; } return (`🔒 This Okta MCP Server is running in READ-ONLY MODE for safety.\n\n` + `✅ Allowed operations: Data queries, exports, and audit operations\n` + `🚫 Blocked operations: Creating, updating, or deleting users, groups, apps, and policies\n\n` + `This prevents accidental data modification in production environments.\n` + `To enable write operations, set READ_ONLY_MODE=false in your environment variables.`); } } //# sourceMappingURL=read-only-middleware.js.map