Kuberwastaken/claurst · error

MCP server ' ' has no URL configured

Error message

MCP server '{}' has no URL configured

What it means

connect_http was given an MCP server config with no `url` field — the entry was routed to the HTTP transport but carries no endpoint URL (hand-edited settings or a stdio-only entry missing its url). Without a URL no streamable-http/SSE connection can be made.

Solutions

  1. Add a `url` field to the server entry in settings
  2. Use the stdio transport type for command-based MCP servers
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src-rust/crates/mcp/src/rmcp_backend.rs:140 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10). Data as JSON: /api/errors/f1941c677e831f0f. Report an issue: GitHub.

Appendix: source

Thrown at src-rust/crates/mcp/src/rmcp_backend.rs:140

        let transport = TokioChildProcess::new(Command::new(&command).configure(|cmd| {
            cmd.args(&config.args);
            cmd.envs(&config.env);
        }))
        .map_err(|e| anyhow::anyhow!("failed to spawn rmcp stdio child for '{}': {}", config.name, e))?;

        let client_info = build_client_info(rmcp_model::ProtocolVersion::default());
        Self::connect_with_transport(config, transport, client_info, "stdio").await
    }

    pub async fn connect_http(
        config: &claurst_core::config::McpServerConfig,
        auth_token: Option<String>,
        protocol_version: rmcp_model::ProtocolVersion,
    ) -> anyhow::Result<Self> {
        let endpoint = config
            .url
            .clone()
            .ok_or_else(|| anyhow::anyhow!("MCP server '{}' has no URL configured", config.name))?;

        let mut transport_config = StreamableHttpClientTransportConfig::with_uri(endpoint);
        if let Some(token) = auth_token {
            transport_config = transport_config.auth_header(token);
        }

        let transport = StreamableHttpClientTransport::from_config(transport_config);
        let client_info = build_client_info(protocol_version);
        Self::connect_with_transport(config, transport, client_info, "http").await
    }

    pub async fn connect_legacy_sse(
        config: &claurst_core::config::McpServerConfig,
        auth_token: Option<String>,
    ) -> anyhow::Result<Self> {
        // Legacy SSE servers still expose the real POST endpoint via
        // `event: endpoint`; keep a thin compatibility shim here and hand the
        // session and capability flow back to rmcp once connected.

View on GitHub (pinned to b0637c97ec)