openai/codex · error · anyhow::Error

exactly one of --command or --url must be provided

Error message

exactly one of --command or --url must be provided

What it means

run_add selects the transport by matching the parsed arguments: a stdio arm (Some(stdio)), a streamable-HTTP arm (Some(streamable_http)), and a catch-all arm that bails `exactly one of --command or --url must be provided`. The catch-all is reached when neither transport flag made it into the parsed arguments, so no McpServerConfig transport can be constructed.

Source

Thrown at codex-rs/cli/src/mcp_cmd.rs:405

                    oauth_client_registration,
                    oauth_resource,
                }),
            ..
        } => (
            McpServerTransportConfig::StreamableHttp {
                url,
                bearer_token_env_var,
                http_headers: None,
                env_http_headers: None,
                http_headers_helper: None,
            },
            oauth_client_id,
            oauth_client_registration
                .map(McpOAuthClientRegistration::from)
                .unwrap_or_default(),
            oauth_resource,
        ),
        AddMcpTransportArgs { .. } => bail!("exactly one of --command or --url must be provided"),
    };

    let new_entry = McpServerConfig {
        auth: Default::default(),
        transport: transport.clone(),
        environment_id: codex_config::DEFAULT_MCP_SERVER_ENVIRONMENT_ID.to_string(),
        enabled: true,
        required: false,
        supports_parallel_tool_calls: false,
        omit_tools_from: None,
        disabled_reason: None,
        startup_timeout_sec: None,
        tool_timeout_sec: None,
        default_tools_approval_mode: None,
        enabled_tools: None,
        disabled_tools: None,
        scopes: None,
        oauth: oauth_client_id

View on GitHub (pinned to 339751715c)

Solutions

  1. Pass exactly one transport: `--command <program> [args...]` for stdio, or `--url https://host/mcp` for streamable HTTP.
  2. Check `codex mcp add --help` for the exact flag names in your codex version.
  3. If you prefer hand-editing, write the [mcp_servers.<name>] table in config.toml directly instead of using mcp add.

Example fix

# before
codex mcp add my-server               # no transport flags at all
# after (stdio)
codex mcp add my-server --command npx -y some-mcp-server
# after (streamable http)
codex mcp add my-server --url https://mcp.example.com/mcp
Defensive patterns

Strategy: validation

Validate before calling

add_server() {
  local name="$1"; shift
  local has_command=0 has_url=0
  for a in "$@"; do
    case "$a" in
      --command) has_command=1 ;;
      --url) has_url=1 ;;
    esac
  done
  if [ "$((has_command + has_url))" -ne 1 ]; then
    echo 'error: pass exactly one of --command or --url' >&2; return 2
  fi
  codex mcp add "$name" "$@"
}

Try / catch

if ! codex mcp add my-server "$@" 2>err.log; then
  grep -q 'exactly one of --command or --url must be provided' err.log && { echo 'usage: codex mcp add <name> (--command <prog> [args...] | --url <https://...>)' >&2; exit 2; }
  exit 1
fi

Prevention

When it happens

Trigger: `codex mcp add my-server` with neither --command nor --url; flag-name typos (--cmd, --uri) so clap binds neither real flag and both transport fields stay None.

Common situations: Assuming `codex mcp add` prompts interactively for the transport; scripts where both flag branches are conditional and neither condition held; renamed flags across codex versions.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/95c8618dfc6f0a8e. Report an issue: GitHub.