Hmbown/CodeWhale · error · anyhow::Error

Unsupported MCP transport '{transport}'. Supported values: s

Error message

Unsupported MCP transport '{transport}'. Supported values: sse

What it means

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.

Source

Thrown at crates/tui/src/mcp.rs:1360

    }
}

fn is_legacy_sse_transport(config: &McpServerConfig) -> bool {
    config
        .transport
        .as_deref()
        .map(|transport| transport.trim().eq_ignore_ascii_case("sse"))
        .unwrap_or(false)
}

pub fn validate_mcp_transport(transport: Option<&str>) -> Result<()> {
    let Some(transport) = transport else {
        return Ok(());
    };
    if transport.trim().eq_ignore_ascii_case("sse") {
        return Ok(());
    }
    anyhow::bail!("Unsupported MCP transport '{transport}'. Supported values: sse");
}

fn response_id_matches(id: Option<&serde_json::Value>, expected_id: &str) -> bool {
    let Some(id) = id else {
        return false;
    };
    if id.as_str() == Some(expected_id) {
        return true;
    }
    id.as_u64()
        .map(|id| id.to_string() == expected_id)
        .unwrap_or(false)
}

// === McpConnection - Async Connection Management ===

/// Manages a single async connection to an MCP server
pub struct McpConnection {

View on GitHub (pinned to 8880682c63)

Solutions

  1. Remove the transport field entirely: command servers are stdio automatically and url servers use streamable HTTP by default.
  2. Keep "transport": "sse" only for legacy HTTP+SSE servers that require the SSE client.
  3. If sse was intended, check spelling, case and surrounding whitespace - it must equal sse after trimming.

Example fix

// before
"my-server": { "url": "https://mcp.example.com", "transport": "http" }
// after: omit transport for the streamable HTTP client
"my-server": { "url": "https://mcp.example.com" }
// (legacy SSE only: "transport": "sse")
Defensive patterns

Strategy: validation

Validate before calling

fn transport_valid(transport: Option<&str>) -> bool {
    transport.is_none_or(|t| t.trim().eq_ignore_ascii_case("sse"))
}

assert!(transport_valid(None));
assert!(transport_valid(Some(" SSE ")));
assert!(!transport_valid(Some("stdio")));

Prevention

When it happens

Trigger: 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.

Common situations: Configs copied from Claude Desktop / Cursor style JSON that uses "type": "stdio"; users trying to explicitly force the streamable HTTP client.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/a93d0af07ab52bf2. Report an issue: GitHub.