zeroclaw-labs/zeroclaw · warning · anyhow::Error
MCP server `{}` does not support resources
Error message
MCP server `{}` does not support resources What it means
list_resources is capability-gated: the server's initialize response did not advertise the resources capability, so the client refuses to send resources/list rather than let the server error downstream. The gate reads the capabilities parsed during handshake, so it reflects exactly what this server build declared.
Source
Thrown at crates/zeroclaw-tools/src/mcp_client.rs:795
let resp = self
.dispatch_rpc(rpc_method, params, tool_timeout, &operation)
.await?;
if let Some(err) = resp.error {
bail!("MCP `{rpc_method}` error {}: {}", err.code, err.message);
}
let result = resp.result.unwrap_or(serde_json::Value::Null);
let server_name = self.inner.lock().await.config.name.clone();
check_result_is_error(&result, rpc_method, &server_name)?;
Ok(result)
}
/// `resources/list` — capability-gated.
pub async fn list_resources(&self, cursor: Option<String>) -> Result<McpResourcesListResult> {
{
let inner = self.inner.lock().await;
if !inner.capabilities.supports_resources() {
bail!(
"MCP server `{}` does not support resources",
inner.config.name
);
}
}
let params = match cursor {
Some(c) => json!({ "cursor": c }),
None => json!({}),
};
let raw = self.dispatch_method("resources/list", params).await?;
serde_json::from_value(raw).context("failed to parse resources/list result")
}
/// `resources/read` — capability-gated.
pub async fn read_resource(&self, uri: &str) -> Result<McpResourceContents> {
{
let inner = self.inner.lock().await;
if !inner.capabilities.supports_resources() {View on GitHub (pinned to 88bb9c8533)
Solutions
- Switch to an MCP server that advertises resources (e.g. a filesystem server) if you need them
- Check the server's initialize response or client debug logs to confirm which capabilities it actually declared
- Guard resource calls so unsupported servers are skipped instead of erroring the whole flow
- If the server should support resources, change to a build that declares them
Example fix
// before
let res = client.list_resources(None).await?;
// after: skip servers without the capability
match client.list_resources(None).await {
Ok(res) => handle(res),
Err(e) if is_unsupported_resources(&e) => skip_server(&name),
Err(e) => return Err(e),
} Defensive patterns
Strategy: validation
Validate before calling
// Probe once per server and cache the result instead of failing per call
let supports = match client.list_resources(None).await {
Ok(_) => true,
Err(e) if is_unsupported_resources(&e) => false,
Err(e) => return Err(e),
};
if supports {
walk_resources(&client).await?;
} Type guard
fn is_unsupported_resources(err: &anyhow::Error) -> bool {
err.to_string().contains("does not support resources")
} Try / catch
Catch and treat as a capability signal, not a fault: skip resource discovery for this server and continue; any other error propagates.
Prevention
- Record each server's advertised capabilities at connect time and gate resource code on them
- Use resource-capable servers (e.g. filesystem) when resource features are required
- Alert on capability changes after server upgrades so gates stay accurate
When it happens
Trigger: Configuring a tools-only or prompts-only MCP server (no resources in its initialize result) and calling list_resources; a proxy that strips capability fields from the initialize result; older server builds predating the resources part of the protocol.
Common situations: Pointing generic resource-walking code at specialized tool servers; version drift where the deployed server build dropped resource support.
Related errors
- MCP `{rpc_method}` error {}: {}
- QQ channel requires the `channel-qq` feature
- Lark channel requires the `channel-lark` feature
- DingTalk channel requires the `channel-dingtalk` feature
- WeCom channel requires the `channel-wecom` feature
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/123bc62bbeee2dcb.
Report an issue: GitHub.