{"record":{"id":"a93d0af07ab52bf2","repo":"Hmbown/CodeWhale","slug":"unsupported-mcp-transport-transport-supported","errorCode":null,"errorMessage":"Unsupported MCP transport '{transport}'. Supported values: sse","messagePattern":"Unsupported MCP transport '(.+?)'\\. Supported values: sse","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp.rs","lineNumber":1360,"sourceCode":"    }\n}\n\nfn is_legacy_sse_transport(config: &McpServerConfig) -> bool {\n    config\n        .transport\n        .as_deref()\n        .map(|transport| transport.trim().eq_ignore_ascii_case(\"sse\"))\n        .unwrap_or(false)\n}\n\npub fn validate_mcp_transport(transport: Option<&str>) -> Result<()> {\n    let Some(transport) = transport else {\n        return Ok(());\n    };\n    if transport.trim().eq_ignore_ascii_case(\"sse\") {\n        return Ok(());\n    }\n    anyhow::bail!(\"Unsupported MCP transport '{transport}'. Supported values: sse\");\n}\n\nfn response_id_matches(id: Option<&serde_json::Value>, expected_id: &str) -> bool {\n    let Some(id) = id else {\n        return false;\n    };\n    if id.as_str() == Some(expected_id) {\n        return true;\n    }\n    id.as_u64()\n        .map(|id| id.to_string() == expected_id)\n        .unwrap_or(false)\n}\n\n// === McpConnection - Async Connection Management ===\n\n/// Manages a single async connection to an MCP server\npub struct McpConnection {","sourceCodeStart":1342,"sourceCodeEnd":1378,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/mcp.rs#L1342-L1378","documentation":"validate_mcp_transport accepts exactly one non-empty transport value - `sse`, compared after trim and ASCII case-insensitively - or no transport at all (crates/tui/src/mcp.rs:1353-1361). Any other value (stdio, http, streamable-http, websocket, typos) is rejected when a server is added via the mcp add path (add_server_config, mcp.rs:4024) or validated through runtime_api. Note what the field actually selects: a url server without transport uses the streamable HTTP transport, `sse` selects the legacy SSE client, and command-based servers are stdio with no transport field.","triggerScenarios":"Adding a server with --transport stdio or writing \"transport\": \"http\" / \"streamable-http\" / \"websocket\" into the MCP config; porting snippets from other MCP clients whose vocabularies use those names.","commonSituations":"Configs copied from Claude Desktop / Cursor style JSON that uses \"type\": \"stdio\"; users trying to explicitly force the streamable HTTP client.","solutions":["Remove the transport field entirely: command servers are stdio automatically and url servers use streamable HTTP by default.","Keep \"transport\": \"sse\" only for legacy HTTP+SSE servers that require the SSE client.","If sse was intended, check spelling, case and surrounding whitespace - it must equal sse after trimming."],"exampleFix":"// before\n\"my-server\": { \"url\": \"https://mcp.example.com\", \"transport\": \"http\" }\n// after: omit transport for the streamable HTTP client\n\"my-server\": { \"url\": \"https://mcp.example.com\" }\n// (legacy SSE only: \"transport\": \"sse\")","handlingStrategy":"validation","validationCode":"fn transport_valid(transport: Option<&str>) -> bool {\n    transport.is_none_or(|t| t.trim().eq_ignore_ascii_case(\"sse\"))\n}\n\nassert!(transport_valid(None));\nassert!(transport_valid(Some(\" SSE \")));\nassert!(!transport_valid(Some(\"stdio\")));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Omit the transport field unless you specifically need the legacy SSE client.","Remember: command => stdio, url (no transport) => streamable HTTP, url + \"sse\" => legacy SSE.","Validate config snippets ported from other MCP clients before writing them."],"tags":["config","mcp","transport","validation"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}