Skip to main content

soma_mcp_client/upstream/pool/
resources.rs

1use crate::upstream::{CapScope, ResourceDescriptor, UpstreamError};
2
3use super::tools::matches_filter;
4
5impl super::UpstreamPool {
6    pub async fn list_resources(
7        &self,
8        upstream: &str,
9    ) -> Result<Vec<ResourceDescriptor>, UpstreamError> {
10        self.ensure_connected(upstream).await?;
11        self.with_entry(upstream, |entry| {
12            if !entry.config.proxy_resources {
13                return Ok(Vec::new());
14            }
15            let resources: Vec<ResourceDescriptor> = entry
16                .snapshot
17                .resources
18                .iter()
19                .filter(|resource| {
20                    matches_filter(entry.config.expose_resources.as_deref(), &resource.uri)
21                })
22                .cloned()
23                .collect();
24            let bytes = serde_json::to_vec(&resources).map_or(usize::MAX, |bytes| bytes.len());
25            self.response_caps()
26                .enforce(CapScope::ResourcesList, bytes)?;
27            Ok(resources)
28        })
29    }
30
31    pub async fn read_resource(
32        &self,
33        upstream: &str,
34        uri: &str,
35    ) -> Result<serde_json::Value, UpstreamError> {
36        self.ensure_connected(upstream).await?;
37        let peer =
38            self.with_entry(upstream, |entry| {
39                if !entry.config.proxy_resources {
40                    return Err(UpstreamError::Unsupported {
41                        upstream: upstream.to_owned(),
42                        capability: "resources/read",
43                    });
44                }
45                entry.live.as_ref().map(|live| live.peer()).ok_or_else(|| {
46                    UpstreamError::Unsupported {
47                        upstream: upstream.to_owned(),
48                        capability: "resources/read",
49                    }
50                })
51            })?;
52        let value = super::live::read_live_resource(upstream, peer, uri.to_owned()).await?;
53        let bytes = serde_json::to_vec(&value).map_or(usize::MAX, |bytes| bytes.len());
54        self.response_caps()
55            .enforce(CapScope::ResourcesRead, bytes)?;
56        Ok(value)
57    }
58}
59
60#[cfg(test)]
61#[path = "resources_tests.rs"]
62mod tests;