Skip to main content

Resources

In the Basics chapter, we learned how to read a resource. In this section, we’ll explore in more detail how deal with resources provided by the MCP server.

Reading a Resource

To read a resource, use the read_resource() method. It requires the tool name and optional arguments.

use neva::prelude::*;

#[tokio::main]
async fn main() -> Result<(), Error> {
let mut client = Client::new()
.with_options(|opt| opt
.with_stdio(
"cargo",
["run", "--manifest-path", "./neva-mcp-server/Cargo.toml"]));

client.connect().await?;

let resource = client.read_resource("res://resource-1").await?

println!("{:?}", result.contents);

client.disconnect().await
}

Contents

In the example above, the read_resource method returns a ReadResourceResult, which contains a Vec of ResourceContents.

You can access individual resource fields using the following methods:

Subscribing to resource updates

Two notifications carry resource changes: notifications/resources/list_changed when the list itself changes (the server must have declared listChanged), and notifications/resources/updated when a specific resource changes (the server must have declared subscribe).

Register the handlers after connect() — they assert on what the server advertises, which is not known until discovery has run:

client.on_resources_changed(|_: Notification| async {
println!("Resource list has been updated");
});

client.on_resource_changed(|n: Notification| async move {
let params = n.params::<SubscribeRequestParams>()
.expect("Expected SubscribeRequestParams");

println!("Resource '{}' has been updated", params.uri);
});

Handlers alone do not make notifications arrive: under MCP 2026-07-28 the client asks for them with a subscriptions/listen stream, which is where the per-resource subscription lives:

let mut subscription = client
.listen(SubscriptionFilter::new()
.with_resources_changed()
.with_resource("res://some-resource"))
.await?;

// ...

subscription.cancel().await?;

See Subscriptions for the filter, the acknowledgment, and the subscription's lifecycle.

Replacing subscribe_to_resource

client.subscribe_to_resource(uri) / unsubscribe_from_resource(uri) are the legacy pair. They stay compiled — the dual-mode fallback still reaches legacy peers — but reject a 2026-07-28 peer with MethodNotFound. Use SubscriptionFilter::with_resource(uri) instead, as above.

Learn By Example

Here you may find the full example

Additional examples