tinyhumansai/openhuman · error · anyhow::Error

MCP error: {err}

Error message

MCP error: {err}

What it means

The HTTP MCP server's JSON-RPC response parsed successfully but contained an `error` object, which is surfaced verbatim (`MCP error: {err}` — code plus message). Like the stdio twin, this is a protocol-level refusal from the server: transport worked, the request was delivered, and the server answered with a structured failure.

Source

Thrown at src/openhuman/mcp/http_client/client.rs:813

                if let Some(data) = first_complete_sse_data(&String::from_utf8_lossy(&raw))? {
                    frame = Some(data);
                    break;
                }
            }
            match frame {
                Some(data) => data,
                // Stream ended without a data frame — fall back to the whole-body
                // parser for a clear "no data frame" error that includes the body.
                None => parse_sse_message(&String::from_utf8_lossy(&raw))?,
            }
        } else {
            let text = response.text().await?;
            serde_json::from_str(&text).map_err(|e| {
                anyhow::anyhow!("Failed to parse MCP JSON response: {e} — body: {text}")
            })?
        };
        if let Some(err) = payload.get("error") {
            anyhow::bail!("MCP error: {err}");
        }
        let result = payload
            .get("result")
            .ok_or_else(|| anyhow::anyhow!("MCP response missing `result`: {payload}"))?
            .clone();
        Ok(ResponseEnvelope {
            result,
            session_id: header_to_string(&headers, HEADER_SESSION_ID),
        })
    }
}

#[cfg(test)]
#[path = "client_tests.rs"]
mod tests;

View on GitHub (pinned to 7491200858)

Solutions

  1. Decode the JSON-RPC error: `-32602` invalid params → align arguments with the tool's `inputSchema` (re-fetch `tools/list`).
  2. Unknown-method/tool → refresh the tool list; the name may have changed or been filtered.
  3. Quota/auth errors → fix the underlying credential or limit, then retry.
  4. Pin the server version if behavior changed after an update.
Defensive patterns

Strategy: try-catch

Try / catch

match client.call_tool(tool, args).await {
    Err(e) => {
        let msg = e.to_string();
        if msg.contains("-32602") { /* fix args against fresh tools/list inputSchema */ }
        else if msg.contains("quota") || msg.contains("rate") { /* backoff, then retry */ }
        else { return Err(e); }
    }
    ok => ok,
}

Prevention

When it happens

Trigger: `tools/call` with arguments failing the server's schema; unknown tool or method names; server-side upstream failures (API quota, expired credentials) mapped into JSON-RPC errors; initialize parameter mistakes.

Common situations: Argument drift after a server upgrade; calling tools discovered from a different server; hosted MCP services returning quota/auth errors inside JSON-RPC; model-generated arguments violating a strict schema.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/14470be91460939c. Report an issue: GitHub.