prism_mcp_rs/client/
enhanced_builder.rs1use crate::client::McpClient;
5use crate::core::enhanced_errors::{McpError, McpResult};
6use crate::protocol::types::{ClientCapabilities, ClientInfo};
7use crate::protocol::ProtocolMode;
8use crate::protocol::TASKS_EXTENSION_ID;
9use std::collections::HashMap;
10use std::time::Duration;
11
12#[derive(Debug, Clone)]
14pub struct RetryConfig {
15 pub max_attempts: Option<u32>,
16 pub initial_delay_ms: u64,
17 pub max_delay_ms: u64,
18 pub backoff_multiplier: f64,
19}
20
21impl Default for RetryConfig {
22 fn default() -> Self {
23 Self {
24 max_attempts: Some(3),
25 initial_delay_ms: 1000,
26 max_delay_ms: 30000,
27 backoff_multiplier: 2.0,
28 }
29 }
30}
31
32#[derive(Debug, Clone)]
34pub struct ConnectionConfig {
35 pub timeout_ms: u64,
36 pub keep_alive: bool,
37 pub compression: bool,
38}
39
40impl Default for ConnectionConfig {
41 fn default() -> Self {
42 Self {
43 timeout_ms: 30000,
44 keep_alive: true,
45 compression: false,
46 }
47 }
48}
49
50#[derive(Debug)]
52pub struct McpClientBuilder {
53 name: Option<String>,
54 version: Option<String>,
55 capabilities: Option<ClientCapabilities>,
56 timeout: Option<Duration>,
57 max_retries: Option<u32>,
58 validate_requests: Option<bool>,
59 validate_responses: Option<bool>,
60 protocol_mode: Option<ProtocolMode>,
61 max_mrtr_rounds: Option<u8>,
62}
63
64impl McpClientBuilder {
65 pub fn new() -> Self {
67 Self {
68 name: None,
69 version: None,
70 capabilities: None,
71 timeout: None,
72 max_retries: None,
73 validate_requests: None,
74 validate_responses: None,
75 protocol_mode: None,
76 max_mrtr_rounds: None,
77 }
78 }
79
80 pub fn name(mut self, name: impl Into<String>) -> Self {
82 self.name = Some(name.into());
83 self
84 }
85
86 pub fn version(mut self, version: impl Into<String>) -> Self {
88 self.version = Some(version.into());
89 self
90 }
91
92 pub fn capabilities(mut self, capabilities: ClientCapabilities) -> Self {
94 self.capabilities = Some(capabilities);
95 self
96 }
97
98 pub fn with_tasks_extension(mut self) -> Self {
100 let capabilities = self.capabilities.get_or_insert_with(Default::default);
101 capabilities
102 .extensions
103 .get_or_insert_with(HashMap::new)
104 .insert(TASKS_EXTENSION_ID.to_string(), serde_json::json!({}));
105 self
106 }
107
108 pub fn timeout(mut self, timeout: Duration) -> Self {
110 self.timeout = Some(timeout);
111 self
112 }
113
114 pub fn max_retries(mut self, retries: u32) -> Self {
116 self.max_retries = Some(retries);
117 self
118 }
119
120 pub fn validate_requests(mut self, validate: bool) -> Self {
122 self.validate_requests = Some(validate);
123 self
124 }
125
126 pub fn validate_responses(mut self, validate: bool) -> Self {
128 self.validate_responses = Some(validate);
129 self
130 }
131
132 pub fn protocol_mode(mut self, mode: ProtocolMode) -> Self {
134 self.protocol_mode = Some(mode);
135 self
136 }
137
138 pub fn max_mrtr_rounds(mut self, rounds: u8) -> Self {
140 self.max_mrtr_rounds = Some(rounds.max(1));
141 self
142 }
143
144 pub fn build(self) -> McpResult<McpClient> {
146 let name = self
147 .name
148 .ok_or_else(|| McpError::validation("Client name is required"))?;
149 let version = self.version.unwrap_or_else(|| "1.0.0".to_string());
150
151 let client_info = ClientInfo::new(name, version);
152 let capabilities = self.capabilities.unwrap_or_default();
153
154 let config = crate::client::mcp_client::ClientConfig {
155 request_timeout_ms: self.timeout.map(|d| d.as_millis() as u64).unwrap_or(30000),
156 max_retries: self.max_retries.unwrap_or(3),
157 retry_delay_ms: 1000,
158 validate_requests: self.validate_requests.unwrap_or(true),
159 validate_responses: self.validate_responses.unwrap_or(true),
160 protocol_mode: self.protocol_mode.unwrap_or_default(),
161 max_mrtr_rounds: self.max_mrtr_rounds.unwrap_or(10),
162 };
163
164 Ok(McpClient::from_parts(client_info, capabilities, config))
165 }
166}
167
168impl Default for McpClientBuilder {
169 fn default() -> Self {
170 Self::new()
171 }
172}
173
174impl McpClientBuilder {
176 pub fn development(name: impl Into<String>) -> Self {
178 Self::new()
179 .name(name)
180 .version("dev")
181 .timeout(Duration::from_secs(10))
182 .max_retries(1)
183 }
184
185 pub fn production(name: impl Into<String>, version: impl Into<String>) -> Self {
190 Self::new()
191 .name(name)
192 .version(version)
193 .timeout(Duration::from_secs(30))
194 .max_retries(3)
195 .validate_requests(true)
196 .validate_responses(true)
197 }
198}