Parent Issue
Part of #475 (MCP Server)
Context
Discussion about avoiding duplication between CLI and MCP implementations.
Current State
- CLI has 3 layers: raw API, human commands, workflows
- MCP server wraps
redis-enterprise / redis-cloud crates directly
- ~381 handler methods across both crates
- Currently implementing first-class MCP tools manually
Future Architecture Options
Option 1: Command Registry Pattern
pub struct Command {
name: &'static str, // "enterprise.database.create"
description: &'static str,
params: Vec<ParamDef>, // typed parameter definitions
handler: AsyncHandler, // async fn(params) -> Result<Value>
}
// Both CLI and MCP consume this registry
let registry = CommandRegistry::new();
Option 2: Derive Macro
#[derive(Command)] // generates CLI args + MCP tool schema
#[command(name = "enterprise.database.create")]
pub struct CreateDatabase {
#[arg(required)]
name: String,
#[arg(default = 100)]
memory_size_mb: u64,
}
Option 3: Thin MCP wrapper over CLI
async fn redisctl_exec(args: Vec<String>) -> Result<Value> {
// Shell out to redisctl -o json
}
Decision
For now: Continue with direct handler wrapping for ~75% raw API coverage.
Revisit architecture after seeing real-world usage patterns.
Questions to Answer Later
- Is raw API coverage enough, or do users need workflow-level MCP tools?
- What's the right abstraction for "one implementation, multiple interfaces"?
- Should we generate MCP tools from handler signatures?
References
Parent Issue
Part of #475 (MCP Server)
Context
Discussion about avoiding duplication between CLI and MCP implementations.
Current State
redis-enterprise/redis-cloudcrates directlyFuture Architecture Options
Option 1: Command Registry Pattern
Option 2: Derive Macro
Option 3: Thin MCP wrapper over CLI
Decision
For now: Continue with direct handler wrapping for ~75% raw API coverage.
Revisit architecture after seeing real-world usage patterns.
Questions to Answer Later
References