soma_mcp_client/upstream/pool/
resources.rs1use 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;