Skip to main content

turbomcp_client/
lib.rs

1//! # `TurboMCP` Client
2//!
3//! MCP (Model Context Protocol) client implementation for connecting to MCP servers
4//! and consuming their capabilities (tools, prompts, resources, and sampling).
5//!
6//! ## Features
7//!
8//! - Connection management with automatic reconnection
9//! - Error handling and recovery mechanisms
10//! - Support for all MCP capabilities including bidirectional sampling
11//! - Elicitation response handling for server-initiated user input requests
12//! - Transport-agnostic design (works with any `Transport` implementation)
13//! - Type-safe protocol communication
14//! - Request/response correlation tracking
15//! - Timeout and cancellation support
16//! - Automatic capability negotiation
17//! - Handler support for server-initiated requests (sampling and elicitation)
18//!
19//! ## Architecture
20//!
21//! The client follows a layered architecture:
22//!
23//! ```text
24//! Application Layer
25//!        ↓
26//! Client API (this crate)
27//!        ↓  
28//! Protocol Layer (turbomcp-protocol)
29//!        ↓
30//! Transport Layer (turbomcp-transport)
31//! ```
32//!
33//! ## Usage
34//!
35//! ```rust,no_run
36//! use turbomcp_client::{Client, ClientBuilder};
37//! use turbomcp_transport::stdio::StdioTransport;
38//!
39//! # async fn example() -> turbomcp_protocol::Result<()> {
40//! // Create a client with stdio transport
41//! let transport = StdioTransport::new();
42//! let mut client = Client::new(transport);
43//!
44//! // Initialize connection and negotiate capabilities
45//! let result = client.initialize().await?;
46//! println!("Connected to: {}", result.server_info.name);
47//!
48//! // List and call tools
49//! let tools = client.list_tools().await?;
50//! for tool in tools {
51//!     println!("Tool: {} - {}", tool.name, tool.description.as_deref().unwrap_or("No description"));
52//! }
53//!
54//! // Access resources
55//! let resources = client.list_resources().await?;
56//! for resource in resources {
57//!     println!("Resource: {} ({})", resource.name, resource.uri);
58//! }
59//! # Ok(())
60//! # }
61//! ```
62//!
63//! ## Elicitation Response Handling
64//!
65//! The client supports handling server-initiated elicitation requests:
66//!
67//! ```rust,no_run
68//! use turbomcp_client::Client;
69//! use std::collections::HashMap;
70//!
71//! // Simple elicitation handling example
72//! async fn handle_server_elicitation() {
73//!     // When server requests user input, you would:
74//!     // 1. Present the schema to the user
75//!     // 2. Collect their input  
76//!     // 3. Send response back to server
77//!     
78//!     let user_preferences: HashMap<String, String> = HashMap::new();
79//!     // Your UI/CLI interaction logic here
80//!     println!("Server requesting user preferences");
81//! }
82//! ```
83//!
84//! ## Sampling Support
85//!
86//! Handle server-initiated sampling requests for LLM capabilities:
87//!
88//! ```rust,no_run
89//! use turbomcp_client::Client;
90//! use turbomcp_client::sampling::SamplingHandler;
91//! use turbomcp_protocol::types::{CreateMessageRequest, CreateMessageResult, Role, Content, StopReason, TextContent};
92//! use std::future::Future;
93//! use std::pin::Pin;
94//!
95//! #[derive(Debug)]
96//! struct MySamplingHandler {
97//!     // Your LLM client would go here
98//! }
99//!
100//! impl SamplingHandler for MySamplingHandler {
101//!     fn handle_create_message(
102//!         &self,
103//!         request_id: String,
104//!         request: CreateMessageRequest
105//!     ) -> Pin<Box<dyn Future<Output = Result<CreateMessageResult, Box<dyn std::error::Error + Send + Sync>>> + Send + '_>> {
106//!         Box::pin(async move {
107//!             // Forward to your LLM provider (OpenAI, Anthropic, etc.)
108//!             // Use request_id for correlation tracking
109//!             // Allows the server to request LLM sampling through the client
110//!
111//!             Ok(CreateMessageResult {
112//!                 role: Role::Assistant,
113//!                 content: Content::Text(
114//!                     TextContent {
115//!                         text: "Response from LLM".to_string(),
116//!                         annotations: None,
117//!                         meta: None,
118//!                     }
119//!                 ),
120//!                 model: "gpt-4".to_string(),
121//!                 stop_reason: Some(StopReason::EndTurn),
122//!                 _meta: None,
123//!             })
124//!         })
125//!     }
126//! }
127//! ```
128//!
129//! ## Error Handling
130//!
131//! The client provides comprehensive error handling with automatic retry logic:
132//!
133//! ```rust,no_run
134//! # use turbomcp_client::Client;
135//! # use turbomcp_transport::stdio::StdioTransport;
136//! # async fn example() -> turbomcp_protocol::Result<()> {
137//! # let mut client = Client::new(StdioTransport::new());
138//! match client.call_tool("my_tool", None, None).await {
139//!     Ok(result) => println!("Tool result: {:?}", result),
140//!     Err(e) => eprintln!("Tool call failed: {}", e),
141//! }
142//! # Ok(())
143//! # }
144//! ```
145
146/// TurboMCP Client version from Cargo.toml
147///
148/// This constant provides easy programmatic access to the current version.
149///
150/// # Example
151///
152/// ```rust
153/// println!("TurboMCP Client version: {}", turbomcp_client::VERSION);
154/// ```
155pub const VERSION: &str = env!("CARGO_PKG_VERSION");
156
157/// TurboMCP Client crate name
158pub const CRATE_NAME: &str = env!("CARGO_PKG_NAME");
159
160pub mod client;
161pub mod handlers;
162pub mod integration;
163pub mod prelude;
164pub mod sampling;
165
166// v3.0 Tower-native middleware
167pub mod middleware;
168
169// Re-export key types for convenience
170pub use client::{ConnectionInfo, ConnectionState, ManagerConfig, ServerGroup, SessionManager};
171
172use std::sync::Arc;
173
174// Re-export Transport trait for generic bounds in integrations
175pub use turbomcp_transport::Transport;
176
177// ============================================================================
178// TOP-LEVEL RE-EXPORTS FOR ERGONOMIC IMPORTS
179// ============================================================================
180
181// Result/Error types - re-export from protocol for consistency
182pub use turbomcp_protocol::{Error, Result};
183
184// Handler types (most commonly used)
185pub use handlers::{
186    // Cancellation (MCP 2025-06-18 spec compliant)
187    CancellationHandler,
188    CancelledNotification,
189    ElicitationAction,
190    // Elicitation
191    ElicitationHandler,
192    ElicitationRequest,
193    ElicitationResponse,
194    // Error handling
195    HandlerError,
196    HandlerResult,
197    // Logging (MCP 2025-06-18 spec compliant)
198    LogHandler,
199    LoggingNotification,
200    PromptListChangedHandler,
201    // List changed handlers (MCP 2025-06-18 spec compliant)
202    ResourceListChangedHandler,
203    // Resource updates (MCP 2025-06-18 spec compliant)
204    ResourceUpdateHandler,
205    ResourceUpdatedNotification,
206    // Roots
207    RootsHandler,
208    ToolListChangedHandler,
209};
210
211// Sampling types
212pub use sampling::{SamplingHandler, ServerInfo, UserInteractionHandler};
213
214// v3.0 Tower middleware
215pub use middleware::{
216    Cache, CacheConfig, CacheLayer, CacheService, McpRequest, McpResponse, Metrics, MetricsLayer,
217    MetricsService, MetricsSnapshot, TracingLayer, TracingService,
218};
219
220// Common protocol types
221pub use turbomcp_protocol::types::{
222    // Resource content types (for processing embedded resources)
223    BlobResourceContents,
224    // Tool result types (for LLM integrations like rig)
225    CallToolResult,
226    // Core types
227    Content,
228    ContentBlock,
229    EmbeddedResource,
230    LogLevel,
231    Prompt,
232    Resource,
233    ResourceContent,
234    ResourceContents,
235    Role,
236    TextResourceContents,
237    Tool,
238};
239
240// Transport re-exports (with feature gates)
241#[cfg(feature = "stdio")]
242pub use turbomcp_transport::stdio::StdioTransport;
243
244#[cfg(feature = "http")]
245pub use turbomcp_transport::streamable_http_client::{
246    RetryPolicy, StreamableHttpClientConfig, StreamableHttpClientTransport,
247};
248
249#[cfg(feature = "tcp")]
250pub use turbomcp_transport::tcp::{TcpTransport, TcpTransportBuilder};
251
252#[cfg(feature = "unix")]
253pub use turbomcp_transport::unix::{UnixTransport, UnixTransportBuilder};
254
255#[cfg(feature = "websocket")]
256pub use turbomcp_transport::websocket_bidirectional::{
257    WebSocketBidirectionalConfig, WebSocketBidirectionalTransport,
258};
259
260/// Client capability configuration
261///
262/// Defines the capabilities that this client supports when connecting to MCP servers.
263/// These capabilities are sent during the initialization handshake to negotiate
264/// which features will be available during the session.
265///
266/// # Examples
267///
268/// ```
269/// use turbomcp_client::ClientCapabilities;
270///
271/// let capabilities = ClientCapabilities {
272///     tools: true,
273///     prompts: true,
274///     resources: true,
275///     sampling: false,
276///     max_concurrent_handlers: 100,
277/// };
278/// ```
279#[derive(Debug, Clone)]
280pub struct ClientCapabilities {
281    /// Whether the client supports tool calling
282    pub tools: bool,
283
284    /// Whether the client supports prompts
285    pub prompts: bool,
286
287    /// Whether the client supports resources
288    pub resources: bool,
289
290    /// Whether the client supports sampling
291    pub sampling: bool,
292
293    /// Maximum concurrent request/notification handlers (default: 100)
294    ///
295    /// This limits how many server-initiated requests/notifications can be processed simultaneously.
296    /// Provides automatic backpressure when the limit is reached.
297    ///
298    /// **Tuning Guide:**
299    /// - Low-resource clients: 50
300    /// - Standard clients: 100 (default)
301    /// - High-performance: 200-500
302    /// - Maximum recommended: 1000
303    pub max_concurrent_handlers: usize,
304}
305
306impl Default for ClientCapabilities {
307    fn default() -> Self {
308        Self {
309            tools: false,
310            prompts: false,
311            resources: false,
312            sampling: false,
313            max_concurrent_handlers: 100,
314        }
315    }
316}
317
318impl ClientCapabilities {
319    /// All capabilities enabled (tools, prompts, resources, sampling)
320    ///
321    /// This is the most comprehensive configuration, enabling full MCP protocol support.
322    ///
323    /// # Example
324    ///
325    /// ```rust
326    /// use turbomcp_client::ClientCapabilities;
327    ///
328    /// let capabilities = ClientCapabilities::all();
329    /// assert!(capabilities.tools);
330    /// assert!(capabilities.prompts);
331    /// assert!(capabilities.resources);
332    /// assert!(capabilities.sampling);
333    /// ```
334    #[must_use]
335    pub fn all() -> Self {
336        Self {
337            tools: true,
338            prompts: true,
339            resources: true,
340            sampling: true,
341            max_concurrent_handlers: 100,
342        }
343    }
344
345    /// Core capabilities without sampling (tools, prompts, resources)
346    ///
347    /// This is the recommended default for most applications. It enables
348    /// all standard MCP features except server-initiated sampling requests.
349    ///
350    /// # Example
351    ///
352    /// ```rust
353    /// use turbomcp_client::ClientCapabilities;
354    ///
355    /// let capabilities = ClientCapabilities::core();
356    /// assert!(capabilities.tools);
357    /// assert!(capabilities.prompts);
358    /// assert!(capabilities.resources);
359    /// assert!(!capabilities.sampling);
360    /// ```
361    #[must_use]
362    pub fn core() -> Self {
363        Self {
364            tools: true,
365            prompts: true,
366            resources: true,
367            sampling: false,
368            max_concurrent_handlers: 100,
369        }
370    }
371
372    /// Minimal capabilities (tools only)
373    ///
374    /// Use this for simple tool-calling clients that don't need prompts,
375    /// resources, or sampling support.
376    ///
377    /// # Example
378    ///
379    /// ```rust
380    /// use turbomcp_client::ClientCapabilities;
381    ///
382    /// let capabilities = ClientCapabilities::minimal();
383    /// assert!(capabilities.tools);
384    /// assert!(!capabilities.prompts);
385    /// assert!(!capabilities.resources);
386    /// assert!(!capabilities.sampling);
387    /// ```
388    #[must_use]
389    pub fn minimal() -> Self {
390        Self {
391            tools: true,
392            prompts: false,
393            resources: false,
394            sampling: false,
395            max_concurrent_handlers: 100,
396        }
397    }
398
399    /// Only tools enabled
400    ///
401    /// Same as `minimal()`, provided for clarity.
402    #[must_use]
403    pub fn only_tools() -> Self {
404        Self::minimal()
405    }
406
407    /// Only resources enabled
408    ///
409    /// Use this for resource-focused clients that don't need tools or prompts.
410    ///
411    /// # Example
412    ///
413    /// ```rust
414    /// use turbomcp_client::ClientCapabilities;
415    ///
416    /// let capabilities = ClientCapabilities::only_resources();
417    /// assert!(!capabilities.tools);
418    /// assert!(!capabilities.prompts);
419    /// assert!(capabilities.resources);
420    /// ```
421    #[must_use]
422    pub fn only_resources() -> Self {
423        Self {
424            tools: false,
425            prompts: false,
426            resources: true,
427            sampling: false,
428            max_concurrent_handlers: 100,
429        }
430    }
431
432    /// Only prompts enabled
433    ///
434    /// Use this for prompt-focused clients that don't need tools or resources.
435    ///
436    /// # Example
437    ///
438    /// ```rust
439    /// use turbomcp_client::ClientCapabilities;
440    ///
441    /// let capabilities = ClientCapabilities::only_prompts();
442    /// assert!(!capabilities.tools);
443    /// assert!(capabilities.prompts);
444    /// assert!(!capabilities.resources);
445    /// ```
446    #[must_use]
447    pub fn only_prompts() -> Self {
448        Self {
449            tools: false,
450            prompts: true,
451            resources: false,
452            sampling: false,
453            max_concurrent_handlers: 100,
454        }
455    }
456
457    /// Only sampling enabled
458    ///
459    /// Use this for clients that exclusively handle server-initiated sampling requests.
460    #[must_use]
461    pub fn only_sampling() -> Self {
462        Self {
463            tools: false,
464            prompts: false,
465            resources: false,
466            sampling: true,
467            max_concurrent_handlers: 100,
468        }
469    }
470}
471
472/// JSON-RPC protocol handler for MCP communication
473// Note: ProtocolClient implementation moved to client/protocol.rs for better modularity
474/// MCP client for communicating with servers
475///
476/// The `Client` struct provides an ergonomic interface for interacting with MCP servers.
477/// It handles protocol complexity internally, exposing clean, type-safe methods.
478///
479/// # Type Parameters
480///
481/// * `T` - The transport implementation used for communication
482///
483/// # Examples
484///
485/// ```rust,no_run
486/// use turbomcp_client::Client;
487/// use turbomcp_transport::stdio::StdioTransport;
488///
489/// # async fn example() -> turbomcp_protocol::Result<()> {
490/// let transport = StdioTransport::new();
491/// let mut client = Client::new(transport);
492///
493/// // Initialize and start using the client
494/// client.initialize().await?;
495/// # Ok(())
496/// # }
497/// ```
498// Re-export Client from the core module
499pub use client::core::Client;
500
501// Thread-safe wrapper for sharing Client across async tasks
502//
503// This wrapper encapsulates the Arc/Mutex complexity and provides a clean API
504// for concurrent access to MCP client functionality. It addresses the limitations
505// identified in PR feedback where Client requires `&mut self` for all operations
506// but needs to be shared across multiple async tasks.
507//
508// # Design Rationale
509//
510// All Client methods require `&mut self` because:
511// - MCP connections maintain state (initialized flag, connection status)
512// - Request correlation tracking for JSON-RPC requires mutation
513// - Handler and plugin registries need mutable access
514//
515// Note: SharedClient has been removed in v2 - Client is now directly cloneable via Arc
516
517// ----------------------------------------------------------------------------
518// Re-exports
519// ----------------------------------------------------------------------------
520
521#[doc = "Result of client initialization"]
522#[doc = ""]
523#[doc = "Contains information about the server and the negotiated capabilities"]
524#[doc = "after a successful initialization handshake."]
525pub use client::config::InitializeResult;
526
527// ServerCapabilities is now imported from turbomcp_protocol::types
528
529/// Connection configuration for the client
530#[derive(Debug, Clone)]
531pub struct ConnectionConfig {
532    /// Request timeout in milliseconds
533    pub timeout_ms: u64,
534
535    /// Maximum number of retry attempts
536    pub max_retries: u32,
537
538    /// Retry delay in milliseconds
539    pub retry_delay_ms: u64,
540
541    /// Keep-alive interval in milliseconds
542    pub keepalive_ms: u64,
543}
544
545impl Default for ConnectionConfig {
546    fn default() -> Self {
547        Self {
548            timeout_ms: 30_000,    // 30 seconds
549            max_retries: 3,        // 3 attempts
550            retry_delay_ms: 1_000, // 1 second
551            keepalive_ms: 60_000,  // 60 seconds
552        }
553    }
554}
555
556/// Builder for configuring and creating MCP clients
557///
558/// Provides a fluent interface for configuring client options before creation.
559/// The enhanced builder pattern supports comprehensive configuration including:
560/// - Protocol capabilities
561/// - Plugin registration
562/// - Handler registration
563/// - Connection settings
564/// - Resilience configuration
565///
566/// # Examples
567///
568/// Basic usage:
569/// ```rust,no_run
570/// use turbomcp_client::ClientBuilder;
571/// use turbomcp_transport::stdio::StdioTransport;
572///
573/// # async fn example() -> turbomcp_protocol::Result<()> {
574/// let client = ClientBuilder::new()
575///     .with_tools(true)
576///     .with_prompts(true)
577///     .with_resources(false)
578///     .build(StdioTransport::new());
579/// # Ok(())
580/// # }
581/// ```
582///
583/// Advanced configuration with Tower middleware:
584/// ```rust,no_run
585/// use turbomcp_client::{ClientBuilder, ConnectionConfig};
586/// use turbomcp_client::middleware::MetricsLayer;
587/// use turbomcp_transport::stdio::StdioTransport;
588/// use tower::ServiceBuilder;
589///
590/// # async fn example() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
591/// let client = ClientBuilder::new()
592///     .with_tools(true)
593///     .with_prompts(true)
594///     .with_resources(true)
595///     .with_sampling(true)
596///     .with_connection_config(ConnectionConfig {
597///         timeout_ms: 60_000,
598///         max_retries: 5,
599///         retry_delay_ms: 2_000,
600///         keepalive_ms: 30_000,
601///     })
602///     .build(StdioTransport::new())
603///     .await?;
604/// # Ok(())
605/// # }
606/// ```
607#[derive(Debug, Default)]
608pub struct ClientBuilder {
609    capabilities: ClientCapabilities,
610    connection_config: ConnectionConfig,
611    elicitation_handler: Option<Arc<dyn crate::handlers::ElicitationHandler>>,
612    log_handler: Option<Arc<dyn crate::handlers::LogHandler>>,
613    resource_update_handler: Option<Arc<dyn crate::handlers::ResourceUpdateHandler>>,
614    // Robustness configuration
615    enable_resilience: bool,
616    retry_config: Option<turbomcp_transport::resilience::RetryConfig>,
617    circuit_breaker_config: Option<turbomcp_transport::resilience::CircuitBreakerConfig>,
618    health_check_config: Option<turbomcp_transport::resilience::HealthCheckConfig>,
619}
620
621// Default implementation is now derived
622
623impl ClientBuilder {
624    /// Create a new client builder
625    ///
626    /// Returns a new builder with default configuration.
627    #[must_use]
628    pub fn new() -> Self {
629        Self::default()
630    }
631
632    // ============================================================================
633    // CAPABILITY CONFIGURATION
634    // ============================================================================
635
636    /// Enable or disable tool support
637    ///
638    /// # Arguments
639    ///
640    /// * `enabled` - Whether to enable tool support
641    #[must_use]
642    pub fn with_tools(mut self, enabled: bool) -> Self {
643        self.capabilities.tools = enabled;
644        self
645    }
646
647    /// Enable or disable prompt support
648    ///
649    /// # Arguments
650    ///
651    /// * `enabled` - Whether to enable prompt support
652    #[must_use]
653    pub fn with_prompts(mut self, enabled: bool) -> Self {
654        self.capabilities.prompts = enabled;
655        self
656    }
657
658    /// Enable or disable resource support
659    ///
660    /// # Arguments
661    ///
662    /// * `enabled` - Whether to enable resource support
663    #[must_use]
664    pub fn with_resources(mut self, enabled: bool) -> Self {
665        self.capabilities.resources = enabled;
666        self
667    }
668
669    /// Enable or disable sampling support
670    ///
671    /// # Arguments
672    ///
673    /// * `enabled` - Whether to enable sampling support
674    #[must_use]
675    pub fn with_sampling(mut self, enabled: bool) -> Self {
676        self.capabilities.sampling = enabled;
677        self
678    }
679
680    /// Set maximum concurrent request/notification handlers
681    ///
682    /// This limits how many server-initiated requests/notifications can be processed simultaneously.
683    /// Provides automatic backpressure when the limit is reached.
684    ///
685    /// # Arguments
686    ///
687    /// * `limit` - Maximum concurrent handlers (default: 100)
688    ///
689    /// # Tuning Guide
690    ///
691    /// - Low-resource clients: 50
692    /// - Standard clients: 100 (default)
693    /// - High-performance: 200-500
694    /// - Maximum recommended: 1000
695    ///
696    /// # Example
697    ///
698    /// ```rust,no_run
699    /// use turbomcp_client::ClientBuilder;
700    /// # use turbomcp_transport::StdioTransport;
701    ///
702    /// let builder = ClientBuilder::new()
703    ///     .with_max_concurrent_handlers(200);
704    /// ```
705    #[must_use]
706    pub fn with_max_concurrent_handlers(mut self, limit: usize) -> Self {
707        self.capabilities.max_concurrent_handlers = limit;
708        self
709    }
710
711    /// Configure all capabilities at once
712    ///
713    /// # Arguments
714    ///
715    /// * `capabilities` - The capabilities configuration
716    #[must_use]
717    pub fn with_capabilities(mut self, capabilities: ClientCapabilities) -> Self {
718        self.capabilities = capabilities;
719        self
720    }
721
722    // ============================================================================
723    // CONNECTION CONFIGURATION
724    // ============================================================================
725
726    /// Configure connection settings
727    ///
728    /// # Arguments
729    ///
730    /// * `config` - The connection configuration
731    #[must_use]
732    pub fn with_connection_config(mut self, config: ConnectionConfig) -> Self {
733        self.connection_config = config;
734        self
735    }
736
737    /// Set request timeout
738    ///
739    /// # Arguments
740    ///
741    /// * `timeout_ms` - Timeout in milliseconds
742    #[must_use]
743    pub fn with_timeout(mut self, timeout_ms: u64) -> Self {
744        self.connection_config.timeout_ms = timeout_ms;
745        self
746    }
747
748    /// Set maximum retry attempts
749    ///
750    /// # Arguments
751    ///
752    /// * `max_retries` - Maximum number of retries
753    #[must_use]
754    pub fn with_max_retries(mut self, max_retries: u32) -> Self {
755        self.connection_config.max_retries = max_retries;
756        self
757    }
758
759    /// Set retry delay
760    ///
761    /// # Arguments
762    ///
763    /// * `delay_ms` - Retry delay in milliseconds
764    #[must_use]
765    pub fn with_retry_delay(mut self, delay_ms: u64) -> Self {
766        self.connection_config.retry_delay_ms = delay_ms;
767        self
768    }
769
770    /// Set keep-alive interval
771    ///
772    /// # Arguments
773    ///
774    /// * `interval_ms` - Keep-alive interval in milliseconds
775    #[must_use]
776    pub fn with_keepalive(mut self, interval_ms: u64) -> Self {
777        self.connection_config.keepalive_ms = interval_ms;
778        self
779    }
780
781    // ============================================================================
782    // ROBUSTNESS & RESILIENCE CONFIGURATION
783    // ============================================================================
784
785    /// Enable resilient transport with circuit breaker, retry, and health checking
786    ///
787    /// When enabled, the transport layer will automatically:
788    /// - Retry failed operations with exponential backoff
789    /// - Use circuit breaker pattern to prevent cascade failures
790    /// - Perform periodic health checks
791    /// - Deduplicate messages
792    ///
793    /// # Examples
794    ///
795    /// ```rust,no_run
796    /// use turbomcp_client::ClientBuilder;
797    /// use turbomcp_transport::stdio::StdioTransport;
798    ///
799    /// let client = ClientBuilder::new()
800    ///     .enable_resilience()
801    ///     .build(StdioTransport::new());
802    /// ```
803    #[must_use]
804    pub fn enable_resilience(mut self) -> Self {
805        self.enable_resilience = true;
806        self
807    }
808
809    /// Configure retry behavior for resilient transport
810    ///
811    /// # Arguments
812    ///
813    /// * `config` - Retry configuration
814    ///
815    /// # Examples
816    ///
817    /// ```rust,no_run
818    /// use turbomcp_client::ClientBuilder;
819    /// use turbomcp_transport::resilience::RetryConfig;
820    /// use turbomcp_transport::stdio::StdioTransport;
821    /// use std::time::Duration;
822    ///
823    /// let client = ClientBuilder::new()
824    ///     .enable_resilience()
825    ///     .with_retry_config(RetryConfig {
826    ///         max_attempts: 5,
827    ///         base_delay: Duration::from_millis(100),
828    ///         max_delay: Duration::from_secs(30),
829    ///         backoff_multiplier: 2.0,
830    ///         jitter_factor: 0.1,
831    ///         retry_on_connection_error: true,
832    ///         retry_on_timeout: true,
833    ///         custom_retry_conditions: Vec::new(),
834    ///     })
835    ///     .build(StdioTransport::new());
836    /// ```
837    #[must_use]
838    pub fn with_retry_config(
839        mut self,
840        config: turbomcp_transport::resilience::RetryConfig,
841    ) -> Self {
842        self.retry_config = Some(config);
843        self.enable_resilience = true; // Auto-enable resilience
844        self
845    }
846
847    /// Configure circuit breaker for resilient transport
848    ///
849    /// # Arguments
850    ///
851    /// * `config` - Circuit breaker configuration
852    ///
853    /// # Examples
854    ///
855    /// ```rust,no_run
856    /// use turbomcp_client::ClientBuilder;
857    /// use turbomcp_transport::resilience::CircuitBreakerConfig;
858    /// use turbomcp_transport::stdio::StdioTransport;
859    /// use std::time::Duration;
860    ///
861    /// let client = ClientBuilder::new()
862    ///     .enable_resilience()
863    ///     .with_circuit_breaker_config(CircuitBreakerConfig {
864    ///         failure_threshold: 5,
865    ///         success_threshold: 2,
866    ///         timeout: Duration::from_secs(60),
867    ///         rolling_window_size: 100,
868    ///         minimum_requests: 10,
869    ///     })
870    ///     .build(StdioTransport::new());
871    /// ```
872    #[must_use]
873    pub fn with_circuit_breaker_config(
874        mut self,
875        config: turbomcp_transport::resilience::CircuitBreakerConfig,
876    ) -> Self {
877        self.circuit_breaker_config = Some(config);
878        self.enable_resilience = true; // Auto-enable resilience
879        self
880    }
881
882    /// Configure health checking for resilient transport
883    ///
884    /// # Arguments
885    ///
886    /// * `config` - Health check configuration
887    ///
888    /// # Examples
889    ///
890    /// ```rust,no_run
891    /// use turbomcp_client::ClientBuilder;
892    /// use turbomcp_transport::resilience::HealthCheckConfig;
893    /// use turbomcp_transport::stdio::StdioTransport;
894    /// use std::time::Duration;
895    ///
896    /// let client = ClientBuilder::new()
897    ///     .enable_resilience()
898    ///     .with_health_check_config(HealthCheckConfig {
899    ///         interval: Duration::from_secs(30),
900    ///         timeout: Duration::from_secs(5),
901    ///         failure_threshold: 3,
902    ///         success_threshold: 1,
903    ///         custom_check: None,
904    ///     })
905    ///     .build(StdioTransport::new());
906    /// ```
907    #[must_use]
908    pub fn with_health_check_config(
909        mut self,
910        config: turbomcp_transport::resilience::HealthCheckConfig,
911    ) -> Self {
912        self.health_check_config = Some(config);
913        self.enable_resilience = true; // Auto-enable resilience
914        self
915    }
916
917    // ============================================================================
918    // HANDLER REGISTRATION
919    // ============================================================================
920
921    /// Register an elicitation handler for processing user input requests
922    ///
923    /// # Arguments
924    ///
925    /// * `handler` - The elicitation handler implementation
926    pub fn with_elicitation_handler(
927        mut self,
928        handler: Arc<dyn crate::handlers::ElicitationHandler>,
929    ) -> Self {
930        self.elicitation_handler = Some(handler);
931        self
932    }
933
934    /// Register a log handler for processing server log messages
935    ///
936    /// # Arguments
937    ///
938    /// * `handler` - The log handler implementation
939    pub fn with_log_handler(mut self, handler: Arc<dyn crate::handlers::LogHandler>) -> Self {
940        self.log_handler = Some(handler);
941        self
942    }
943
944    /// Register a resource update handler for processing resource change notifications
945    ///
946    /// # Arguments
947    ///
948    /// * `handler` - The resource update handler implementation
949    pub fn with_resource_update_handler(
950        mut self,
951        handler: Arc<dyn crate::handlers::ResourceUpdateHandler>,
952    ) -> Self {
953        self.resource_update_handler = Some(handler);
954        self
955    }
956
957    // ============================================================================
958    // BUILD METHODS
959    // ============================================================================
960
961    /// Build a client with the configured options
962    ///
963    /// Creates a new client instance with all the configured options. The client
964    /// will be initialized with the registered plugins, handlers, and providers.
965    ///
966    /// # Arguments
967    ///
968    /// * `transport` - The transport to use for the client
969    ///
970    /// # Returns
971    ///
972    /// Returns a configured `Client` instance wrapped in a Result for async setup.
973    ///
974    /// # Examples
975    ///
976    /// ```rust,no_run
977    /// use turbomcp_client::ClientBuilder;
978    /// use turbomcp_transport::stdio::StdioTransport;
979    ///
980    /// # async fn example() -> turbomcp_protocol::Result<()> {
981    /// let client = ClientBuilder::new()
982    ///     .with_tools(true)
983    ///     .with_prompts(true)
984    ///     .build(StdioTransport::new())
985    ///     .await?;
986    /// # Ok(())
987    /// # }
988    /// ```
989    pub async fn build<T: Transport + 'static>(self, transport: T) -> Result<Client<T>> {
990        // Create base client with capabilities
991        let client = Client::with_capabilities(transport, self.capabilities);
992
993        // Register handlers
994        if let Some(handler) = self.elicitation_handler {
995            client.set_elicitation_handler(handler);
996        }
997        if let Some(handler) = self.log_handler {
998            client.set_log_handler(handler);
999        }
1000        if let Some(handler) = self.resource_update_handler {
1001            client.set_resource_update_handler(handler);
1002        }
1003
1004        Ok(client)
1005    }
1006
1007    /// Build a client with resilient transport (circuit breaker, retry, health checking)
1008    ///
1009    /// When resilience features are enabled via `enable_resilience()` or any resilience
1010    /// configuration method, this wraps the transport in a `TurboTransport` that provides:
1011    /// - Automatic retry with exponential backoff
1012    /// - Circuit breaker pattern for fast failure
1013    /// - Health checking and monitoring
1014    /// - Message deduplication
1015    ///
1016    /// # Arguments
1017    ///
1018    /// * `transport` - The base transport to wrap with resilience features
1019    ///
1020    /// # Returns
1021    ///
1022    /// Returns a configured `Client<TurboTransport>` instance.
1023    ///
1024    /// # Errors
1025    ///
1026    /// Returns an error if plugin initialization fails.
1027    ///
1028    /// # Examples
1029    ///
1030    /// ```rust,no_run
1031    /// use turbomcp_client::ClientBuilder;
1032    /// use turbomcp_transport::stdio::StdioTransport;
1033    /// use turbomcp_transport::resilience::{RetryConfig, CircuitBreakerConfig, HealthCheckConfig};
1034    /// use std::time::Duration;
1035    ///
1036    /// # async fn example() -> turbomcp_protocol::Result<()> {
1037    /// let client = ClientBuilder::new()
1038    ///     .with_retry_config(RetryConfig {
1039    ///         max_attempts: 5,
1040    ///         base_delay: Duration::from_millis(200),
1041    ///         ..Default::default()
1042    ///     })
1043    ///     .with_circuit_breaker_config(CircuitBreakerConfig {
1044    ///         failure_threshold: 3,
1045    ///         timeout: Duration::from_secs(30),
1046    ///         ..Default::default()
1047    ///     })
1048    ///     .with_health_check_config(HealthCheckConfig {
1049    ///         interval: Duration::from_secs(15),
1050    ///         timeout: Duration::from_secs(5),
1051    ///         ..Default::default()
1052    ///     })
1053    ///     .build_resilient(StdioTransport::new())
1054    ///     .await?;
1055    /// # Ok(())
1056    /// # }
1057    /// ```
1058    pub async fn build_resilient<T: Transport + 'static>(
1059        self,
1060        transport: T,
1061    ) -> Result<Client<turbomcp_transport::resilience::TurboTransport>> {
1062        use turbomcp_transport::resilience::TurboTransport;
1063
1064        // Get configurations or use defaults
1065        let retry_config = self.retry_config.unwrap_or_default();
1066        let circuit_config = self.circuit_breaker_config.unwrap_or_default();
1067        let health_config = self.health_check_config.unwrap_or_default();
1068
1069        // Wrap transport in TurboTransport
1070        let robust_transport = TurboTransport::new(
1071            Box::new(transport),
1072            retry_config,
1073            circuit_config,
1074            health_config,
1075        );
1076
1077        // Create client with resilient transport
1078        let client = Client::with_capabilities(robust_transport, self.capabilities);
1079
1080        // Register handlers
1081        if let Some(handler) = self.elicitation_handler {
1082            client.set_elicitation_handler(handler);
1083        }
1084        if let Some(handler) = self.log_handler {
1085            client.set_log_handler(handler);
1086        }
1087        if let Some(handler) = self.resource_update_handler {
1088            client.set_resource_update_handler(handler);
1089        }
1090
1091        Ok(client)
1092    }
1093
1094    /// Build a client synchronously with basic configuration only
1095    ///
1096    /// This is a convenience method for simple use cases.
1097    ///
1098    /// # Arguments
1099    ///
1100    /// * `transport` - The transport to use for the client
1101    ///
1102    /// # Returns
1103    ///
1104    /// Returns a configured `Client` instance.
1105    ///
1106    /// # Examples
1107    ///
1108    /// ```rust,no_run
1109    /// use turbomcp_client::ClientBuilder;
1110    /// use turbomcp_transport::stdio::StdioTransport;
1111    ///
1112    /// let client = ClientBuilder::new()
1113    ///     .with_tools(true)
1114    ///     .build_sync(StdioTransport::new());
1115    /// ```
1116    pub fn build_sync<T: Transport + 'static>(self, transport: T) -> Client<T> {
1117        let client = Client::with_capabilities(transport, self.capabilities);
1118
1119        // Register synchronous handlers only
1120        if let Some(handler) = self.elicitation_handler {
1121            client.set_elicitation_handler(handler);
1122        }
1123        if let Some(handler) = self.log_handler {
1124            client.set_log_handler(handler);
1125        }
1126        if let Some(handler) = self.resource_update_handler {
1127            client.set_resource_update_handler(handler);
1128        }
1129
1130        client
1131    }
1132
1133    // ============================================================================
1134    // CONFIGURATION ACCESS
1135    // ============================================================================
1136
1137    /// Get the current capabilities configuration
1138    #[must_use]
1139    pub fn capabilities(&self) -> &ClientCapabilities {
1140        &self.capabilities
1141    }
1142
1143    /// Get the current connection configuration
1144    #[must_use]
1145    pub fn connection_config(&self) -> &ConnectionConfig {
1146        &self.connection_config
1147    }
1148
1149    /// Check if any handlers are registered
1150    #[must_use]
1151    pub fn has_handlers(&self) -> bool {
1152        self.elicitation_handler.is_some()
1153            || self.log_handler.is_some()
1154            || self.resource_update_handler.is_some()
1155    }
1156}
1157
1158// Re-export types for public API
1159pub use turbomcp_protocol::types::ServerCapabilities as PublicServerCapabilities;