Skip to content

MCP: Consider unified command layer architecture #532

@joshrotenberg

Description

@joshrotenberg

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions