{"record":{"id":"9ef4ef2281118a1e","repo":"Hmbown/CodeWhale","slug":"provide-either-a-command-or-url-for-mcp-server-n","errorCode":null,"errorMessage":"Provide either a command or URL for MCP server '{name}'.","messagePattern":"Provide either a command or URL for MCP server '(.+?)'\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp.rs","lineNumber":4022,"sourceCode":"            format!(\"Failed to create MCP config directory {}\", parent.display())\n        })?;\n    }\n    let template = mcp_template_json()?;\n    write_atomic(path, template.as_bytes())\n        .with_context(|| format!(\"Failed to write MCP config {}\", path.display()))?;\n    Ok(status)\n}\n\npub fn add_server_config(\n    path: &Path,\n    name: String,\n    command: Option<String>,\n    url: Option<String>,\n    args: Vec<String>,\n    transport: Option<String>,\n) -> Result<()> {\n    if command.is_none() && url.is_none() {\n        anyhow::bail!(\"Provide either a command or URL for MCP server '{name}'.\");\n    }\n    validate_mcp_transport(transport.as_deref())?;\n    let mut cfg = load_config(path)?;\n    cfg.servers.insert(\n        name,\n        McpServerConfig {\n            command,\n            args,\n            env: HashMap::new(),\n            cwd: None,\n            url,\n            transport,\n            connect_timeout: None,\n            execute_timeout: None,\n            read_timeout: None,\n            disabled: false,\n            enabled: true,\n            required: false,","sourceCodeStart":4004,"sourceCodeEnd":4040,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/mcp.rs#L4004-L4040","documentation":"add_server_config (backing the 'add MCP server' flow) requires exactly one launch style: a local command (stdio) or a URL (HTTP/SSE). Passing neither would create a server entry that can never start, so it fails fast with this message before the config file is read or written.","triggerScenarios":"Calling add_server_config with both command and url as None; a CLI add invoked without --command or --url; a form/UI submission that drops empty-string fields into None.","commonSituations":"Scripting the CLI and forgetting the launch flag; UI wiring that maps empty inputs to None; typos in flag names so values never reach the call.","solutions":["Provide either a command (stdio server) or a URL (remote HTTP/SSE server) for the add operation","For remote servers pass the URL plus the correct transport; for local servers pass command and args","Fix the CLI/UI code path that collects the fields before calling add_server_config"],"exampleFix":"# before\n$ codewhale mcp add my-server\n\n# after\n$ codewhale mcp add my-server --command npx --args -y --args some-server","handlingStrategy":"validation","validationCode":"// Validate before calling add_server_config:\nanyhow::ensure!(command.is_some() || url.is_some(), \"supply --command or --url for '{name}'\");\nadd_server_config(&path, name, command, url, args, transport)?;","typeGuard":"fn has_launch_method(command: &Option<String>, url: &Option<String>) -> bool {\n    command.is_some() || url.is_some()\n}","tryCatchPattern":null,"preventionTips":["Validate the add-server form/CLI arguments client-side before submission","Map empty strings to explicit errors at the UI boundary instead of None","Document that exactly one of command (stdio) or url (HTTP/SSE) is required"],"tags":["mcp","config","validation"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}