{"record":{"id":"14470be91460939c","repo":"tinyhumansai/openhuman","slug":"mcp-error-err","errorCode":null,"errorMessage":"MCP error: {err}","messagePattern":"MCP error: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/openhuman/mcp/http_client/client.rs","lineNumber":813,"sourceCode":"                if let Some(data) = first_complete_sse_data(&String::from_utf8_lossy(&raw))? {\n                    frame = Some(data);\n                    break;\n                }\n            }\n            match frame {\n                Some(data) => data,\n                // Stream ended without a data frame — fall back to the whole-body\n                // parser for a clear \"no data frame\" error that includes the body.\n                None => parse_sse_message(&String::from_utf8_lossy(&raw))?,\n            }\n        } else {\n            let text = response.text().await?;\n            serde_json::from_str(&text).map_err(|e| {\n                anyhow::anyhow!(\"Failed to parse MCP JSON response: {e} — body: {text}\")\n            })?\n        };\n        if let Some(err) = payload.get(\"error\") {\n            anyhow::bail!(\"MCP error: {err}\");\n        }\n        let result = payload\n            .get(\"result\")\n            .ok_or_else(|| anyhow::anyhow!(\"MCP response missing `result`: {payload}\"))?\n            .clone();\n        Ok(ResponseEnvelope {\n            result,\n            session_id: header_to_string(&headers, HEADER_SESSION_ID),\n        })\n    }\n}\n\n#[cfg(test)]\n#[path = \"client_tests.rs\"]\nmod tests;\n","sourceCodeStart":795,"sourceCodeEnd":829,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/mcp/http_client/client.rs#L795-L829","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Decode the JSON-RPC error: `-32602` invalid params → align arguments with the tool's `inputSchema` (re-fetch `tools/list`).","Unknown-method/tool → refresh the tool list; the name may have changed or been filtered.","Quota/auth errors → fix the underlying credential or limit, then retry.","Pin the server version if behavior changed after an update."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match client.call_tool(tool, args).await {\n    Err(e) => {\n        let msg = e.to_string();\n        if msg.contains(\"-32602\") { /* fix args against fresh tools/list inputSchema */ }\n        else if msg.contains(\"quota\") || msg.contains(\"rate\") { /* backoff, then retry */ }\n        else { return Err(e); }\n    }\n    ok => ok,\n}","preventionTips":["Schema-validate tool arguments client-side against tools/list inputSchema.","Refresh tool schemas whenever a server updates; pin versions to avoid drift.","Distinguish transport errors (MCP HTTP ...) from server errors (MCP error ...) in handling."],"tags":["mcp","http","json-rpc","server-error"],"backgroundTag":"json-rpc-error","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}