soma_mcp_client/upstream/pool/
prompts.rs1use crate::upstream::{CapScope, PromptDescriptor, UpstreamError};
2
3use super::tools::matches_filter;
4
5impl super::UpstreamPool {
6 pub async fn list_prompts(
7 &self,
8 upstream: &str,
9 ) -> Result<Vec<PromptDescriptor>, UpstreamError> {
10 self.ensure_connected(upstream).await?;
11 self.with_entry(upstream, |entry| {
12 if !entry.config.proxy_prompts {
13 return Ok(Vec::new());
14 }
15 let prompts: Vec<PromptDescriptor> = entry
16 .snapshot
17 .prompts
18 .iter()
19 .filter(|prompt| {
20 matches_filter(entry.config.expose_prompts.as_deref(), &prompt.name)
21 })
22 .cloned()
23 .collect();
24 let bytes = serde_json::to_vec(&prompts).map_or(usize::MAX, |bytes| bytes.len());
25 self.response_caps().enforce(CapScope::PromptsList, bytes)?;
26 Ok(prompts)
27 })
28 }
29
30 pub async fn get_prompt(
31 &self,
32 upstream: &str,
33 name: &str,
34 arguments: Option<serde_json::Map<String, serde_json::Value>>,
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_prompts {
40 return Err(UpstreamError::Unsupported {
41 upstream: upstream.to_owned(),
42 capability: "prompts/get",
43 });
44 }
45 entry.live.as_ref().map(|live| live.peer()).ok_or_else(|| {
46 UpstreamError::Unsupported {
47 upstream: upstream.to_owned(),
48 capability: "prompts/get",
49 }
50 })
51 })?;
52 let value =
53 super::live::get_live_prompt(upstream, peer, name.to_owned(), arguments).await?;
54 let bytes = serde_json::to_vec(&value).map_or(usize::MAX, |bytes| bytes.len());
55 self.response_caps().enforce(CapScope::PromptsGet, bytes)?;
56 Ok(value)
57 }
58}
59
60#[cfg(test)]
61#[path = "prompts_tests.rs"]
62mod tests;