Kuberwastaken/claurst · error · anyhow::Error

MCP server ' ': tool ' ' call failed

Error message

MCP server '{}': tool '{}' call failed: {}

What it means

McpClient::call_tool forwards a tools/call to the server backend and wraps any backend error with the server name and tool name for context. The trailing `{}` contains the underlying rmcp/transport error, so the root cause (JSON-RPC error, timeout, connection drop, tool returning is_error) is in the wrapped cause.

Solutions

  1. Read the wrapped cause in the message to identify the concrete failure
  2. Validate arguments against the tool's inputSchema (from tools/list) before calling
  3. Confirm the tool name exists on that server via tools/list
  4. Retry the call if the cause is a timeout/connection error; restart the server if it crashed
Defensive patterns

Strategy: try-catch

Try / catch

match client.call_tool(name, args).await {
    Err(e) if e.to_string().contains("call failed") => {
        eprintln!("tool {name} failed: {e:#}"); // inspect full cause chain
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling call_tool(name, arguments) on a connected MCP client where the server rejects or fails the call: unknown tool on that server, invalid arguments schema, server-side exception, timeout, or connection lost mid-call.

Common situations: Wrong tool arguments not matching the server's inputSchema; tool execution crashed on the server; MCP server hung and the request timed out; connection dropped after a restart.

Related errors


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

Appendix: source

Thrown at src-rust/crates/mcp/src/lib.rs:686

        /// already have env vars expanded via `expand_server_config`.
        pub async fn connect_stdio(config: &McpServerConfig) -> anyhow::Result<Self> {
            let backend = crate::rmcp_backend::RmcpClientBackend::connect_stdio(config).await?;
            Ok(Self::from_backend(Arc::new(backend)))
        }

        // ---- High-level API -----------------------------------------------

        pub async fn list_tools(&self) -> anyhow::Result<Vec<McpTool>> {
            self.backend()?.list_tools().await
        }

        pub async fn call_tool(
            &self,
            name: &str,
            arguments: Option<Value>,
        ) -> anyhow::Result<CallToolResult> {
            self.backend()?.call_tool(name, arguments).await.map_err(|e| {
                anyhow::anyhow!(
                    "MCP server '{}': tool '{}' call failed: {}",
                    self.server_name,
                    name,
                    e
                )
            })
        }

        pub async fn list_resources(&self) -> anyhow::Result<Vec<McpResource>> {
            let mut resources = self.backend()?.list_resources().await?;
            apply_resource_templates(&mut resources);
            Ok(resources)
        }

        pub async fn read_resource(&self, uri: &str) -> anyhow::Result<ResourceContents> {
            self.backend()?.read_resource(uri).await
        }

View on GitHub (pinned to b0637c97ec)