{"record":{"id":"1eeefce162ddcf19","repo":"Hmbown/CodeWhale","slug":"mcp-server-name-config-must-have-either-comma","errorCode":null,"errorMessage":"MCP server '{name}' config must have either 'command' or 'url'","messagePattern":"MCP server '(.+?)' config must have either 'command' or 'url'","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp.rs","lineNumber":1647,"sourceCode":"                if let Err(e) = http.try_establish_session().await {\n                    tracing::debug!(\n                        target: \"mcp\",\n                        server = %name,\n                        error = %e,\n                        \"session-establishment GET skipped; proceeding with POST initialize\"\n                    );\n                }\n                Box::new(http)\n            }\n        } else if let Some(command) = &config.command {\n            Box::new(StdioTransport::spawn(\n                &name,\n                command,\n                &config,\n                cancel_token.clone(),\n            )?)\n        } else {\n            anyhow::bail!(\"MCP server '{name}' config must have either 'command' or 'url'\");\n        };\n        // Revalidate after transport construction as well: remote setup may\n        // await DNS/TLS/SSE preflight, and a concurrent process can revoke the\n        // receipt during that interval. Initialization and catalog discovery\n        // never start under a stale generation.\n        if let Some(source) = config.reviewed_plugin.as_ref() {\n            source.validate_before_use(&name, \"initialize\")?;\n        }\n        let authority_watch = authority_watch.map(PendingAuthorityWatch::disarm);\n\n        let mut conn = Self {\n            name: name.clone(),\n            transport,\n            tools: Vec::new(),\n            resources: Vec::new(),\n            resource_templates: Vec::new(),\n            prompts: Vec::new(),\n            request_id: AtomicU64::new(1),","sourceCodeStart":1629,"sourceCodeEnd":1665,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/mcp.rs#L1629-L1665","documentation":"McpServerConfig must describe either a local subprocess (command, with optional args/env/cwd) or a remote endpoint (url). connect_with_policy tries url first, then command, and when both are absent there is nothing to build a transport from (crates/tui/src/mcp.rs:1639-1648). add_server_config pre-rejects the same shape at config-write time with its own message.","triggerScenarios":"A servers entry containing only args/env/headers with no command or url; serde defaults leaving both None after a typo'd key like \"cmd\" or \"executable\" (unknown keys are ignored).","commonSituations":"Hand-edited MCP config with key typos; config ported from another client's schema where the fields nest differently; partial edits that deleted the command line.","solutions":["Add \"command\": \"...\" (plus args) for a stdio server, or \"url\": \"https://...\" for a remote server, to the entry.","Check key spelling exactly - command and url; unrecognized alternatives silently deserialize to None.","Validate the file shape against a freshly generated template (mcp init/config template) after editing."],"exampleFix":"// before\n\"fetch\": { \"args\": [\"-y\", \"mcp-server-fetch\"] }\n// after\n\"fetch\": { \"command\": \"npx\", \"args\": [\"-y\", \"mcp-server-fetch\"] }","handlingStrategy":"validation","validationCode":"fn server_config_has_transport(cfg: &McpServerConfig) -> bool {\n    cfg.command.is_some() || cfg.url.is_some()\n}\n\n// Run over the parsed config before handing it to the connection manager:\nfor (name, cfg) in &config.servers {\n    assert!(server_config_has_transport(cfg), \"server '{name}' needs 'command' or 'url'\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use exactly the keys command and url; unknown keys are silently ignored.","Validate config files after hand edits against the generated template.","Prefer the mcp add path, which pre-rejects entries missing both fields."],"tags":["config","mcp","validation"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}