Skip to main content

prism_mcp_rs/client/
fluent_interfaces.rs

1//! Fluent interfaces for resources and prompts
2
3use crate::core::enhanced_errors::{McpError, McpResult};
4use crate::protocol::{
5    messages::{
6        ListPromptsResult, ListResourcesResult, ReadResourceResult, SubscribeResourceResult,
7    },
8    types::GetPromptResult,
9};
10use serde_json::Value;
11use std::collections::HashMap;
12
13/// Fluent interface for resource operations
14pub struct ResourcesBuilder<'a> {
15    client: &'a crate::client::McpClient,
16}
17
18impl<'a> ResourcesBuilder<'a> {
19    pub(crate) fn new(client: &'a crate::client::McpClient) -> Self {
20        Self { client }
21    }
22
23    /// Read a resource by URI
24    pub async fn read(self, uri: impl Into<String>) -> McpResult<ReadResourceResult> {
25        self.client
26            .read_resource(uri.into())
27            .await
28            .map_err(|e| McpError::internal(e.to_string()))
29    }
30
31    /// List available resources
32    pub async fn list(self) -> McpResult<ListResourcesResult> {
33        self.client
34            .list_resources(None)
35            .await
36            .map_err(|e| McpError::internal(e.to_string()))
37    }
38
39    /// Subscribe to resource updates
40    pub async fn subscribe(self, uri: impl Into<String>) -> McpResult<SubscribeResourceResult> {
41        self.client
42            .subscribe_resource(uri.into())
43            .await
44            .map_err(|e| McpError::internal(e.to_string()))
45    }
46}
47
48/// Fluent interface for prompt operations
49pub struct PromptsBuilder<'a> {
50    client: &'a crate::client::McpClient,
51    prompt_name: Option<String>,
52    arguments: HashMap<String, String>,
53}
54
55impl<'a> PromptsBuilder<'a> {
56    pub(crate) fn new(client: &'a crate::client::McpClient) -> Self {
57        Self {
58            client,
59            prompt_name: None,
60            arguments: HashMap::new(),
61        }
62    }
63
64    /// Set the prompt to get
65    pub fn get(mut self, name: impl Into<String>) -> Self {
66        self.prompt_name = Some(name.into());
67        self
68    }
69
70    /// Add arguments (converts values to strings)
71    pub fn args(mut self, args: impl Into<Value>) -> Self {
72        if let Value::Object(map) = args.into() {
73            for (k, v) in map {
74                self.arguments.insert(k, v.to_string());
75            }
76        }
77        self
78    }
79
80    /// Add a single argument
81    pub fn arg(mut self, key: impl Into<String>, value: impl ToString) -> Self {
82        self.arguments.insert(key.into(), value.to_string());
83        self
84    }
85
86    /// Execute the prompt
87    pub async fn execute(self) -> McpResult<GetPromptResult> {
88        let prompt_name = self
89            .prompt_name
90            .ok_or_else(|| McpError::validation("Prompt name is required"))?;
91
92        self.client
93            .get_prompt(
94                prompt_name,
95                if self.arguments.is_empty() {
96                    None
97                } else {
98                    Some(self.arguments)
99                },
100            )
101            .await
102            .map_err(|e| McpError::internal(e.to_string()))
103    }
104
105    /// List available prompts
106    pub async fn list(self) -> McpResult<ListPromptsResult> {
107        self.client
108            .list_prompts(None)
109            .await
110            .map_err(|e| McpError::internal(e.to_string()))
111    }
112}