zeroclaw-labs/zeroclaw · error · anyhow::Error

MCP server `{server_name}` rejected initialize: {:?}

Error message

MCP server `{server_name}` rejected initialize: {:?}

What it means

During connect, the client sends the MCP initialize request; this error means the server answered with a JSON-RPC error object instead of a result — a protocol-level rejection of the handshake, distinct from a timeout or a crashed process. The server's error code and message are embedded via Debug formatting of the error field.

Source

Thrown at crates/zeroclaw-tools/src/mcp_client.rs:74

                "version": env!("CARGO_PKG_VERSION")
            }
        }),
    );

    let init_lifecycle = McpRequestLifecycle::uncoordinated(epoch);
    let init_resp = timeout(
        Duration::from_secs(RECV_TIMEOUT_SECS),
        transport.send_and_recv(&init_req, &init_lifecycle),
    )
    .await
    .with_context(|| {
        format!(
            "MCP server `{server_name}` timed out after {RECV_TIMEOUT_SECS}s waiting for initialize response"
        )
    })??;

    if init_resp.error.is_some() {
        bail!(
            "MCP server `{server_name}` rejected initialize: {:?}",
            init_resp.error
        );
    }

    // Parse server-advertised capabilities from the initialize result.
    let capabilities = init_resp
        .result
        .as_ref()
        .map(McpServerCapabilities::from_init_result)
        .unwrap_or_default();

    // Notify the server the client is initialized (notifications expect no
    // response). Best effort — ignore errors.
    let notif = JsonRpcRequest::notification("notifications/initialized", json!({}));
    let notif_lifecycle = McpRequestLifecycle::uncoordinated(epoch);
    let _ = transport.send_and_recv(&notif, &notif_lifecycle).await;

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Read the embedded error field — its code and message say exactly what the server rejected
  2. Run the configured command standalone and confirm it speaks MCP (e.g. with an MCP inspector) before reconnecting
  3. Fix the command/args/env in the MCP server config; for HTTP servers verify the URL and required headers
  4. Pin or upgrade the server to a version whose MCP protocol revision the client supports

Example fix

# before
[minecraft]
command = "mc-server"

# after
[minecraft]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
Defensive patterns

Strategy: try-catch

Validate before calling

// Fail fast at startup instead of mid-task
match client_connect(&server_config).await {
    Ok(c) => c,
    Err(e) if e.to_string().contains("rejected initialize") => {
        log_and_alert("MCP server misconfigured: {}", e);
        return Err(e);
    }
    Err(e) => return Err(e),
}

Type guard

fn is_handshake_rejected(err: &anyhow::Error) -> bool {
    err.to_string().contains("rejected initialize")
}

Try / catch

Treat as fatal for this server: do not retry the same config. Catch at connect time, surface the embedded server error, and take the server out of rotation until its command/args/env are fixed.

Prevention

When it happens

Trigger: Running a non-MCP program as the configured command; wrong args or env causing the server to reject initialize; a server build that only speaks an incompatible MCP protocol version; an HTTP endpoint answering the initialize route with a JSON-RPC error (404, auth required).

Common situations: Typos in the MCP server command; pointing the config at a plain OpenAI-plugin/HTTP API instead of an MCP server; version drift after upgrading the server package; auth-protected HTTP MCP endpoints missing required headers.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/a2ddf3addac60292. Report an issue: GitHub.