Kuberwastaken/claurst · error · anyhow::Error

Bridge session registration failed: authentication error

Error message

Bridge session registration failed: authentication error (HTTP {}).\nYour token may be invalid or expired.\nGet a new token from https://claude.ai (Settings → Remote Control).

What it means

`RmcpBackend::connect_stdio` (src-rust/crates/mcp/src/rmcp_backend.rs:120) spawns the MCP server as a child process over stdio using `McpServerConfig`. If the config has no `command` field, the `ok_or_else` on the clone produces "MCP server '<name>' has no command configured". The library cannot launch a stdio MCP server without a command to execute.

Solutions

  1. Add the `command` field to the MCP server config entry, e.g. `"command": "npx"`.
  2. Check the key spelling in the config file — it must be `command`, not `cmd` or `executable`.
  3. If the server is remote (HTTP/SSE), use the transport/config path intended for remote servers instead of `connect_stdio`.
  4. Validate the config against `McpServerConfig` (serde) before connecting to catch missing fields early.

Example fix

// before (mcp servers config)
{ "name": "my-server", "args": ["-y", "@some/mcp-server"] }
// after
{ "name": "my-server", "command": "npx", "args": ["-y", "@some/mcp-server"] }
Defensive patterns

Strategy: validation

Validate before calling

// validate server configs before connecting
for cfg in &settings.mcp_servers {
    if cfg.command.is_none() {
        bail!("MCP server '{}' is missing the 'command' field", cfg.name);
    }
}

Prevention

When it happens

Trigger: `config.command` is None when calling `connect_stdio` — an MCP server entry in settings/config specifies a name (and maybe args/env) but omits the executable command, typically for a server intended to be reached via HTTP/SSE instead of stdio.

Common situations: Config file entry like `{"name": "my-server", "args": ["-y", "pkg"]}` missing the `command` key; user added a remote MCP server but the code path chose stdio transport; a typo'd key (`cmd` instead of `command`) so it deserialized as None.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at src-rust/crates/bridge/src/lib.rs:997

    let resp = http
        .post(&register_url)
        .bearer_auth(&token)
        .header("anthropic-version", "2023-06-01")
        .header("anthropic-beta", "environments-2025-11-01")
        .json(&body)
        .send()
        .await
        .context("start_bridge_session: HTTP POST failed")?;

    let status = resp.status().as_u16();

    match status {
        200 | 201 => {
            info!(session_id = %session_id, "Bridge session registered successfully");
        }
        401 | 403 => {
            anyhow::bail!(
                "Bridge session registration failed: authentication error (HTTP {}).\n\
                 Your token may be invalid or expired.\n\
                 Get a new token from https://claude.ai (Settings → Remote Control).",
                status
            );
        }
        404 => {
            // The /api/bridge/sessions endpoint may not exist in all deployments.
            // Fall through to synthetic session URL (best-effort mode).
            warn!(
                session_id = %session_id,
                "Bridge registration endpoint not found (HTTP 404) — \
                 using local session ID without server validation"
            );
        }
        _ => {
            let body_text = resp.text().await.unwrap_or_default();
            anyhow::bail!(

View on GitHub (pinned to b0637c97ec)