Kuberwastaken/claurst · error
rmcp list_tools failed
Error message
rmcp list_tools failed: {} What it means
Raised in `RmcpClientBackend::list_tools` when the underlying rmcp peer's `list_all_tools()` future fails. The rmcp peer round-trips a `tools/list` JSON-RPC request to the MCP server; any failure — transport error, JSON-RPC error response from the server, timeout, or a closed session — is surfaced here with a uniform `rmcp list_tools failed: <cause>` message. The original rmcp error is preserved after the colon.
Solutions
- Read the inner error: 'method not found' means the server lacks tools support; 'transport closed' means reconnect.
- Reconnect the MCP backend (restart the session) and retry list_tools.
- Verify the MCP server actually implements the `tools` capability (check its docs/capabilities line at startup).
- If the session is stale (server restarted), recreate the client instead of reusing the old peer handle.
Example fix
// before: assuming tools always exist
let tools = backend.list_tools().await?;
// after: degrade gracefully when the server has no tools capability
let tools = match backend.list_tools().await {
Ok(t) => t,
Err(e) if e.to_string().contains("method not found") => Vec::new(),
Err(e) => return Err(e),
}; Defensive patterns
Strategy: try-catch
Validate before calling
fn server_supports_tools(init_caps: &ServerCapabilities) -> bool {
init_caps.tools.is_some()
} Try / catch
match backend.list_tools().await {
Ok(tools) => tools,
Err(e) if e.to_string().contains("method not found") => Vec::new(),
Err(e) => return Err(e.into()),
} Prevention
- Inspect the server's initialize capabilities and only call list_tools when tools are advertised.
- Recreate the backend after any MCP server restart; a stale peer handle fails all calls.
- Cache the tool list with a TTL instead of re-listing constantly.
- Read the inner rmcp error before retrying — capability errors are permanent, transport errors are not.
When it happens
Trigger: Calling `McpClientBackend::list_tools` on an rmcp backend when the server rejects `tools/list`: server does not support the tools capability, session was closed/restarted, transport send/receive failed, or the server returned a JSON-RPC error (e.g. -32601 method not found).
Common situations: MCP server that implements only prompts/resources but not tools; server restarted between connect and list; legacy SSE endpoint stale after reconnect; server-side timeout on a very large tool listing; user runs an /mcp tools command against a misconfigured server.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- rmcp call_tool ' ' failed
- rmcp list_resources failed
- rmcp list_prompts failed
- rmcp read_resource ' ' failed
- rmcp get_prompt ' ' failed
AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/f2c6ca2b4eb1be8f.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/mcp/src/rmcp_backend.rs:508
Ok(())
}
#[async_trait]
impl McpClientBackend for RmcpClientBackend {
fn kind(&self) -> McpBackendKind {
McpBackendKind::Rmcp
}
fn snapshot(&self) -> McpClientSnapshot {
self.snapshot.clone()
}
async fn list_tools(&self) -> anyhow::Result<Vec<McpTool>> {
let tools = self
.peer
.list_all_tools()
.await
.map_err(|e| anyhow::anyhow!("rmcp list_tools failed: {}", e))?;
Ok(tools.into_iter().map(convert_tool).collect())
}
async fn call_tool(
&self,
name: &str,
arguments: Option<Value>,
) -> anyhow::Result<CallToolResult> {
let mut params = rmcp_model::CallToolRequestParams::new(name.to_string());
if let Some(arguments) = arguments {
params = params.with_arguments(json_value_to_object(arguments)?);
}
let result = self
.peer
.call_tool(params)
.await
.map_err(|e| anyhow::anyhow!("rmcp call_tool '{}' failed: {}", name, e))?;
Ok(convert_call_tool_result(result))View on GitHub (pinned to b0637c97ec)