Hmbown/CodeWhale · error · anyhow::Error

Choose exactly one server mode: --mcp, --http/--mobile/--web

Error message

Choose exactly one server mode: --mcp, --http/--mobile/--web, or --acp

What it means

validate_serve_mode_selection counts the selected transport families — mcp, the http group (--http/--mobile/--web collapse into one), and acp — and requires exactly one. This bail fires both when nothing was selected (bare `codewhale serve`) and when two different transports were requested (e.g. --mcp --acp), because one process serves exactly one protocol.

Source

Thrown at crates/tui/src/lib.rs:1295

    mcp: bool,
    http: bool,
    mobile: bool,
    web: bool,
    acp: bool,
) -> Result<bool> {
    if http && mobile {
        bail!("--http and --mobile are mutually exclusive; choose one");
    }
    if web && (http || mobile) {
        bail!("--web is mutually exclusive with --http and --mobile");
    }
    let http_selected = http || mobile || web;
    let selected_modes = [mcp, http_selected, acp]
        .into_iter()
        .filter(|selected| *selected)
        .count();
    if selected_modes != 1 {
        bail!("Choose exactly one server mode: --mcp, --http/--mobile/--web, or --acp");
    }
    Ok(http_selected)
}

#[derive(Subcommand, Debug, Clone)]
enum McpCommand {
    /// List configured MCP servers
    List,
    /// Create a template MCP config at the configured path
    Init {
        /// Overwrite an existing MCP config file
        #[arg(long, default_value_t = false)]
        force: bool,
    },
    /// Connect to MCP servers and report status
    Connect {
        /// Optional server name to connect to
        #[arg(value_name = "SERVER")]

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Pass exactly one mode: --mcp for the MCP stdio server, one of --http/--mobile/--web for the HTTP API, or --acp for the ACP server
  2. If you need several protocols, run one codewhale serve process per mode
  3. Check launcher templates/systemd units for a flag that renders empty

Example fix

# before
codewhale serve                       # or: codewhale serve --mcp --acp

# after
codewhale serve --mcp                 # exactly one mode
Defensive patterns

Strategy: validation

Validate before calling

modes=0
$MCP && modes=$((modes+1))
{ $HTTP || $MOBILE || $WEB; } && modes=$((modes+1))
$ACP && modes=$((modes+1))
[ "$modes" -ne 1 ] && { echo 'exactly one of --mcp / --http-family / --acp required'; exit 2; }

Type guard

fn serve_mode_count_ok(mcp: bool, http_selected: bool, acp: bool) -> bool {
    [mcp, http_selected, acp].iter().filter(|s| **s).count() == 1
}

Prevention

When it happens

Trigger: `codewhale serve` with no mode flag at all; `codewhale serve --mcp --acp`; `codewhale serve --http --mcp`; launchers that default to passing no flags while assuming an implicit mode.

Common situations: Expecting MCP to be the default and omitting the flag; migrating a serve invocation between MCP and HTTP/ACP eras of the CLI; systemd/launcher units that lost their mode flag in templating.

Understand the failure class

Background: "--flag is required" and "must specify" CLI errors: how missing-required-flag validation works and how to fix it — this error's family across 20 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/0d35836cf460cef8. Report an issue: GitHub.