Version: 1.0.0
Target Release: v2.4.0 - v2.6.0 (Q1 2027)
Last Updated: December 2025
Status: Planning
This document outlines the enterprise features roadmap for CyberChef MCP Server, including authentication, authorization, audit logging, distributed architecture, and observability. These features enable production deployments in organizations with strict security, compliance, and operational requirements.
Enterprise Requirements Analysis
Requirement
Priority
Release
OAuth 2.1 Authentication
P0
v2.4.0
Role-Based Authorization
P0
v2.4.0
Audit Logging
P0
v2.4.0
API Key Management
P1
v2.4.0
Multi-Tenancy
P1
v2.4.0
Requirement
Priority
Release
Horizontal Scaling
P0
v2.5.0
High Availability
P0
v2.5.0
Health Checks
P0
v2.5.0
Graceful Shutdown
P0
v2.5.0
Observability Requirements
Requirement
Priority
Release
Distributed Tracing
P0
v2.6.0
Metrics (Prometheus)
P0
v2.6.0
Structured Logging
P0
v2.6.0
Dashboards
P1
v2.6.0
Authentication Architecture
MCP Authorization Specification
The MCP Authorization specification (finalized June 2025) designates MCP servers as OAuth Resource Servers (not Authorization Servers). This means:
CyberChef MCP Server validates tokens, doesn't issue them
Integration with external Identity Providers (IdP)
Support for multiple authorization servers
+------------------+ +------------------+ +------------------+
| | | | | |
| MCP Client |---->| CyberChef MCP |---->| Auth Server |
| | | (Resource Svr) | | (Keycloak, etc) |
+------------------+ +------------------+ +------------------+
| | |
| 1. Get Token | |
|------------------------|----------------------->|
| | |
|<-----------------------|------------------------|
| 2. Access Token | |
| | |
| 3. Request + Token | |
|----------------------->| |
| | 4. Validate Token |
| |----------------------->|
| | |
| |<-----------------------|
| | 5. Token Claims |
| | |
|<-----------------------| |
| 6. Response | |
import { jwtVerify , createRemoteJWKSet } from 'jose' ;
class TokenValidator {
constructor ( config ) {
this . config = config ;
this . jwks = new Map ( ) ;
}
async validate ( token ) {
const header = this . decodeHeader ( token ) ;
const issuer = this . findIssuer ( header ) ;
if ( ! issuer ) {
throw new AuthenticationError ( 'Unknown token issuer' ) ;
}
const jwks = await this . getJWKS ( issuer ) ;
const { payload } = await jwtVerify ( token , jwks , {
issuer : issuer . issuer ,
audience : this . config . audience ,
clockTolerance : this . config . clockTolerance || 30
} ) ;
return {
valid : true ,
claims : payload ,
userId : payload . sub ,
roles : payload . roles || payload [ 'realm_access' ] ?. roles || [ ] ,
permissions : payload . permissions || [ ]
} ;
}
async getJWKS ( issuer ) {
if ( ! this . jwks . has ( issuer . issuer ) ) {
const jwks = createRemoteJWKSet ( new URL ( issuer . jwksUri ) ) ;
this . jwks . set ( issuer . issuer , jwks ) ;
}
return this . jwks . get ( issuer . issuer ) ;
}
}
Identity Provider Integration
{
"oauth" : {
"authorizationServers" : [{
"issuer" : " https://keycloak.example.com/realms/main" ,
"jwksUri" : " https://keycloak.example.com/realms/main/protocol/openid-connect/certs" ,
"audience" : " cyberchef-mcp" ,
"rolesClaim" : " realm_access.roles"
}]
}
}
{
"oauth" : {
"authorizationServers" : [{
"issuer" : " https://your-tenant.auth0.com/" ,
"jwksUri" : " https://your-tenant.auth0.com/.well-known/jwks.json" ,
"audience" : " https://cyberchef-mcp.example.com" ,
"rolesClaim" : " https://cyberchef-mcp.example.com/roles"
}]
}
}
{
"oauth" : {
"authorizationServers" : [{
"issuer" : " https://your-org.okta.com/oauth2/default" ,
"jwksUri" : " https://your-org.okta.com/oauth2/default/v1/keys" ,
"audience" : " api://cyberchef-mcp" ,
"rolesClaim" : " groups"
}]
}
}
Role-Based Access Control (RBAC)
+------------------+
| Roles |
+------------------+
| admin |
| operator |
| viewer |
| developer |
+------------------+
|
v
+------------------+
| Permissions |
+------------------+
| operation:read |
| operation:execute|
| recipe:read |
| recipe:write |
| recipe:execute |
| plugin:manage |
| config:read |
| config:write |
| audit:read |
| tenant:admin |
+------------------+
const permissions = {
// Operation permissions
'operation:read' : 'List and describe operations' ,
'operation:execute' : 'Execute operations' ,
// Recipe permissions
'recipe:read' : 'View saved recipes' ,
'recipe:write' : 'Create and modify recipes' ,
'recipe:execute' : 'Execute saved recipes' ,
'recipe:delete' : 'Delete recipes' ,
// Plugin permissions
'plugin:read' : 'List plugins' ,
'plugin:install' : 'Install plugins' ,
'plugin:uninstall' : 'Remove plugins' ,
'plugin:manage' : 'Full plugin management' ,
// Configuration permissions
'config:read' : 'View configuration' ,
'config:write' : 'Modify configuration' ,
// Audit permissions
'audit:read' : 'Access audit logs' ,
'audit:export' : 'Export audit logs' ,
// Tenant permissions (for multi-tenancy)
'tenant:admin' : 'Tenant administration' ,
'tenant:create' : 'Create sub-tenants' ,
// System permissions
'system:admin' : 'Full system access'
} ;
{
"roles" : {
"viewer" : {
"description" : " Read-only access" ,
"permissions" : [
" operation:read" ,
" recipe:read"
]
},
"operator" : {
"description" : " Execute operations and recipes" ,
"permissions" : [
" operation:read" ,
" operation:execute" ,
" recipe:read" ,
" recipe:execute"
]
},
"developer" : {
"description" : " Full recipe and plugin access" ,
"permissions" : [
" operation:read" ,
" operation:execute" ,
" recipe:*" ,
" plugin:read"
]
},
"admin" : {
"description" : " Full system access" ,
"permissions" : [" *" ]
}
}
}
class AuthorizationMiddleware {
async check ( request , requiredPermission ) {
const user = request . user ;
if ( ! user ) {
throw new AuthenticationError ( 'Not authenticated' ) ;
}
const userPermissions = await this . getUserPermissions ( user ) ;
if ( ! this . hasPermission ( userPermissions , requiredPermission ) ) {
throw new AuthorizationError (
`Permission denied: ${ requiredPermission } ` ,
{ userId : user . id , required : requiredPermission }
) ;
}
return true ;
}
hasPermission ( userPermissions , required ) {
// Check for wildcard
if ( userPermissions . includes ( '*' ) ) return true ;
// Check for exact match
if ( userPermissions . includes ( required ) ) return true ;
// Check for category wildcard (e.g., recipe:* matches recipe:read)
const [ category ] = required . split ( ':' ) ;
if ( userPermissions . includes ( `${ category } :*` ) ) return true ;
return false ;
}
}
interface AuditEvent {
// Event identification
id : string ; // UUID
timestamp : string ; // ISO 8601
version : string ; // Schema version
// Event classification
type : AuditEventType ; // operation.execute, auth.login, etc.
category : AuditCategory ; // authentication, authorization, data, admin
severity : AuditSeverity ; // info, warning, error, critical
// Actor information
actor : {
type : 'user' | 'service' | 'system' ;
id : string ;
email ?: string ;
roles : string [ ] ;
ip ?: string ;
userAgent ?: string ;
} ;
// Resource information
resource : {
type : 'operation' | 'recipe' | 'plugin' | 'config' | 'user' ;
id : string ;
name ?: string ;
} ;
// Action details
action : string ; // read, create, update, delete, execute
result : 'success' | 'failure' ;
reason ?: string ; // Failure reason
// Context
context : {
tenantId ?: string ;
sessionId ?: string ;
requestId : string ;
traceId ?: string ;
} ;
// Metadata
metadata : Record < string , any > ; // Operation-specific data
}
type AuditEventType =
| 'auth.login'
| 'auth.logout'
| 'auth.token_refresh'
| 'auth.failed'
| 'operation.execute'
| 'operation.failed'
| 'recipe.create'
| 'recipe.update'
| 'recipe.delete'
| 'recipe.execute'
| 'plugin.install'
| 'plugin.uninstall'
| 'config.update'
| 'tenant.create'
| 'tenant.update' ;
class AuditLogger {
constructor ( config ) {
this . config = config ;
this . outputs = this . initializeOutputs ( config . outputs ) ;
}
async log ( event ) {
const enrichedEvent = this . enrich ( event ) ;
const validated = this . validate ( enrichedEvent ) ;
// Write to all configured outputs
await Promise . all (
this . outputs . map ( output => output . write ( validated ) )
) ;
}
enrich ( event ) {
return {
...event ,
id : event . id || uuidv4 ( ) ,
timestamp : event . timestamp || new Date ( ) . toISOString ( ) ,
version : '1.0.0' ,
context : {
...event . context ,
serverVersion : this . config . serverVersion ,
environment : this . config . environment
}
} ;
}
// Convenience methods
async authSuccess ( actor , metadata = { } ) {
await this . log ( {
type : 'auth.login' ,
category : 'authentication' ,
severity : 'info' ,
actor,
resource : { type : 'user' , id : actor . id } ,
action : 'login' ,
result : 'success' ,
metadata
} ) ;
}
async operationExecute ( actor , operation , input , output , duration ) {
await this . log ( {
type : 'operation.execute' ,
category : 'data' ,
severity : 'info' ,
actor,
resource : { type : 'operation' , id : operation . name } ,
action : 'execute' ,
result : 'success' ,
metadata : {
inputSize : input . length ,
outputSize : output . length ,
duration
}
} ) ;
}
}
class FileAuditOutput {
constructor ( config ) {
this . path = config . path ;
this . rotation = config . rotation ; // daily, weekly, size-based
}
async write ( event ) {
const line = JSON . stringify ( event ) + '\n' ;
await fs . appendFile ( this . getFilePath ( ) , line ) ;
}
getFilePath ( ) {
const date = new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] ;
return path . join ( this . path , `audit-${ date } .log` ) ;
}
}
class ElasticsearchAuditOutput {
constructor ( config ) {
this . client = new Client ( { node : config . url } ) ;
this . index = config . index || 'cyberchef-audit' ;
}
async write ( event ) {
await this . client . index ( {
index : `${ this . index } -${ this . getDateSuffix ( ) } ` ,
body : event
} ) ;
}
}
+------------------+
| Load Balancer |
+------------------+
|
+------------------+
| Tenant Resolver |
| - Header |
| - Subdomain |
| - API Key |
+------------------+
|
+------------------+
| Tenant Context |
+------------------+
|
+----+----+
| |
+-------+ +-------+
|Tenant | |Tenant |
| A | | B |
+-------+ +-------+
class TenantContext {
constructor ( tenantId , config ) {
this . tenantId = tenantId ;
this . config = config ;
}
getStorage ( ) {
return new TenantStorage ( this . tenantId ) ;
}
getRecipeRepository ( ) {
return new RecipeRepository ( {
prefix : `tenant:${ this . tenantId } :`
} ) ;
}
getQuota ( ) {
return this . config . quotas [ this . tenantId ] || this . config . defaultQuota ;
}
}
// Middleware to resolve tenant
function tenantMiddleware ( req , res , next ) {
const tenantId = req . headers [ 'x-tenant-id' ] ||
req . subdomains [ 0 ] ||
extractFromApiKey ( req . headers . authorization ) ;
if ( ! tenantId ) {
return res . status ( 400 ) . json ( { error : 'Tenant not specified' } ) ;
}
req . tenant = new TenantContext ( tenantId , config ) ;
next ( ) ;
}
+------------------+
| Load Balancer |
+------------------+
|
+----+----+
| | |
+-----+ +-----+ +-----+
|Pod 1| |Pod 2| |Pod 3|
+-----+ +-----+ +-----+
| | |
+----+----+
|
+------------------+
| Redis Cluster |
| - Sessions |
| - Cache |
| - Pub/Sub |
+------------------+
|
+------------------+
| PostgreSQL |
| - Recipes |
| - Audit Logs |
| - Config |
+------------------+
class RedisSessionStore {
constructor ( redisClient , options = { } ) {
this . redis = redisClient ;
this . prefix = options . prefix || 'cyberchef:session:' ;
this . ttl = options . ttl || 3600 ;
}
async get ( sessionId ) {
const data = await this . redis . get ( this . prefix + sessionId ) ;
return data ? JSON . parse ( data ) : null ;
}
async set ( sessionId , data ) {
await this . redis . setex (
this . prefix + sessionId ,
this . ttl ,
JSON . stringify ( data )
) ;
}
async destroy ( sessionId ) {
await this . redis . del ( this . prefix + sessionId ) ;
}
async touch ( sessionId ) {
await this . redis . expire ( this . prefix + sessionId , this . ttl ) ;
}
}
// Kubernetes-compatible health endpoints
app . get ( '/health/live' , ( req , res ) => {
// Liveness: is the process alive?
res . status ( 200 ) . json ( { status : 'ok' } ) ;
} ) ;
app . get ( '/health/ready' , async ( req , res ) => {
// Readiness: can we serve traffic?
const checks = await Promise . all ( [
checkRedis ( ) ,
checkDatabase ( ) ,
checkOperations ( )
] ) ;
const allHealthy = checks . every ( c => c . healthy ) ;
res . status ( allHealthy ? 200 : 503 ) . json ( {
status : allHealthy ? 'ok' : 'degraded' ,
checks
} ) ;
} ) ;
app . get ( '/health/startup' , async ( req , res ) => {
// Startup: has initialization completed?
if ( serverInitialized ) {
res . status ( 200 ) . json ( { status : 'ok' } ) ;
} else {
res . status ( 503 ) . json ( { status : 'starting' } ) ;
}
} ) ;
OpenTelemetry Integration
import { NodeSDK } from '@opentelemetry/sdk-node' ;
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node' ;
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc' ;
import { PrometheusExporter } from '@opentelemetry/exporter-prometheus' ;
const sdk = new NodeSDK ( {
serviceName : 'cyberchef-mcp' ,
traceExporter : new OTLPTraceExporter ( {
url : process . env . OTEL_EXPORTER_OTLP_ENDPOINT
} ) ,
metricReader : new PrometheusExporter ( {
port : 9090
} ) ,
instrumentations : [
getNodeAutoInstrumentations ( )
]
} ) ;
sdk . start ( ) ;
const meter = opentelemetry . metrics . getMeter ( 'cyberchef-mcp' ) ;
const operationCounter = meter . createCounter ( 'cyberchef_operations_total' , {
description : 'Total operations executed'
} ) ;
const operationDuration = meter . createHistogram ( 'cyberchef_operation_duration_seconds' , {
description : 'Operation execution duration'
} ) ;
// Usage
operationCounter . add ( 1 , { operation : 'to_base64' , status : 'success' } ) ;
operationDuration . record ( 0.015 , { operation : 'to_base64' } ) ;
Control
Implementation
Access Control
OAuth 2.1, RBAC
Audit Logging
Complete audit trail
Change Management
Git, deployment logs
Encryption
TLS, encryption at rest
Availability
HA architecture
Requirement
Implementation
Access Control
RBAC with PHI restrictions
Audit Trail
Comprehensive logging
Encryption
TLS 1.3, AES-256 at rest
Minimum Necessary
Role-based access
Business Associate
BAA template provided
Requirement
Implementation
Consent
Configurable consent tracking
Right to Access
Audit log export
Right to Erasure
Data deletion tools
Data Portability
Export in standard formats
Privacy by Design
Minimal data collection
Release
Features
Timeline
v2.4.0
Auth, RBAC, Audit, Multi-tenant
January 2027
v2.5.0
Scaling, HA, Health Checks
February 2027
v2.6.0
OpenTelemetry, Dashboards
March 2027
Document Owner: TBD
Review Cycle: Monthly
Next Review: December 2026