pub struct Client<T: Transport> { /* private fields */ }
Expand description
MCP client for communicating with servers
The Client
struct provides a beautiful, ergonomic interface for interacting with MCP servers.
It handles all protocol complexity internally, exposing only clean, type-safe methods.
§Type Parameters
T
- The transport implementation used for communication
§Examples
use turbomcp_client::Client;
use turbomcp_transport::stdio::StdioTransport;
let transport = StdioTransport::new();
let mut client = Client::new(transport);
// Initialize and start using the client
client.initialize().await?;
Implementations§
Source§impl<T: Transport> Client<T>
impl<T: Transport> Client<T>
Sourcepub fn new(transport: T) -> Self
pub fn new(transport: T) -> Self
Create a new client with the specified transport
Creates a new MCP client instance with default capabilities.
The client must be initialized before use by calling initialize()
.
§Arguments
transport
- The transport implementation to use for communication
§Examples
use turbomcp_client::Client;
use turbomcp_transport::stdio::StdioTransport;
let transport = StdioTransport::new();
let client = Client::new(transport);
Sourcepub fn with_capabilities(transport: T, capabilities: ClientCapabilities) -> Self
pub fn with_capabilities(transport: T, capabilities: ClientCapabilities) -> Self
Create a new client with custom capabilities
§Arguments
transport
- The transport implementation to usecapabilities
- The client capabilities to negotiate
§Examples
use turbomcp_client::{Client, ClientCapabilities};
use turbomcp_transport::stdio::StdioTransport;
let capabilities = ClientCapabilities {
tools: true,
prompts: true,
resources: false,
sampling: false,
};
let transport = StdioTransport::new();
let client = Client::with_capabilities(transport, capabilities);
Sourcepub fn set_sampling_handler(&mut self, handler: Arc<dyn SamplingHandler>)
pub fn set_sampling_handler(&mut self, handler: Arc<dyn SamplingHandler>)
Set the sampling handler for processing server-initiated sampling requests
§Arguments
handler
- The handler implementation for sampling requests
§Examples
use turbomcp_client::{Client, sampling::SamplingHandler};
use turbomcp_transport::stdio::StdioTransport;
use turbomcp_protocol::types::{CreateMessageRequest, CreateMessageResult};
use async_trait::async_trait;
use std::sync::Arc;
#[derive(Debug)]
struct ExampleHandler;
#[async_trait]
impl SamplingHandler for ExampleHandler {
async fn handle_create_message(
&self,
_request: CreateMessageRequest,
) -> Result<CreateMessageResult, Box<dyn std::error::Error + Send + Sync>> {
// Handle sampling request
todo!("Implement sampling logic")
}
}
let mut client = Client::new(StdioTransport::new());
client.set_sampling_handler(Arc::new(ExampleHandler));
Sourcepub async fn process_message(&mut self) -> Result<bool>
pub async fn process_message(&mut self) -> Result<bool>
Process incoming messages from the server
This method should be called in a loop to handle server-initiated requests like sampling. It processes one message at a time.
§Returns
Returns Ok(true)
if a message was processed, Ok(false)
if no message was available.
§Examples
let mut client = Client::new(StdioTransport::new());
// Process messages in background
tokio::spawn(async move {
loop {
if let Err(e) = client.process_message().await {
eprintln!("Error processing message: {}", e);
}
}
});
Sourcepub async fn initialize(&mut self) -> Result<InitializeResult>
pub async fn initialize(&mut self) -> Result<InitializeResult>
Initialize the connection with the MCP server
Performs the initialization handshake with the server, negotiating capabilities and establishing the protocol version. This method must be called before any other operations can be performed.
§Returns
Returns an InitializeResult
containing server information and negotiated capabilities.
§Errors
Returns an error if:
- The transport connection fails
- The server rejects the initialization request
- Protocol negotiation fails
§Examples
let mut client = Client::new(StdioTransport::new());
let result = client.initialize().await?;
println!("Server: {} v{}", result.server_info.name, result.server_info.version);
Sourcepub async fn list_tools(&mut self) -> Result<Vec<Tool>>
pub async fn list_tools(&mut self) -> Result<Vec<Tool>>
List all available tools from the MCP server
Returns a list of complete tool definitions with schemas that can be used for form generation, validation, and documentation. Tools represent executable functions provided by the server.
§Returns
Returns a vector of complete Tool
objects with schemas and metadata.
§Errors
Returns an error if:
- The client is not initialized
- The server doesn’t support tools
- The request fails
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
let tools = client.list_tools().await?;
for tool in tools {
println!("Tool: {} - {}", tool.name, tool.description.as_deref().unwrap_or("No description"));
// Access full inputSchema for form generation
let schema = &tool.input_schema;
}
Sourcepub async fn list_tool_names(&mut self) -> Result<Vec<String>>
pub async fn list_tool_names(&mut self) -> Result<Vec<String>>
List available tool names from the MCP server
Returns only the tool names for cases where full schemas are not needed.
For most use cases, prefer list_tools()
which provides complete tool definitions.
§Returns
Returns a vector of tool names available on the server.
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
let tool_names = client.list_tool_names().await?;
for name in tool_names {
println!("Available tool: {}", name);
}
Sourcepub async fn call_tool(
&mut self,
name: &str,
arguments: Option<HashMap<String, Value>>,
) -> Result<Value>
pub async fn call_tool( &mut self, name: &str, arguments: Option<HashMap<String, Value>>, ) -> Result<Value>
Call a tool on the server
Executes a tool on the server with the provided arguments.
§Arguments
name
- The name of the tool to callarguments
- Optional arguments to pass to the tool
§Returns
Returns the result of the tool execution.
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
let mut args = HashMap::new();
args.insert("input".to_string(), serde_json::json!("test"));
let result = client.call_tool("my_tool", Some(args)).await?;
println!("Tool result: {:?}", result);
Sourcepub async fn complete(
&mut self,
handler_name: &str,
argument_value: &str,
) -> Result<CompletionResponse>
pub async fn complete( &mut self, handler_name: &str, argument_value: &str, ) -> Result<CompletionResponse>
Request completion suggestions from the server
§Arguments
handler_name
- The completion handler nameargument_value
- The partial value to complete
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
let result = client.complete("complete_path", "/usr/b").await?;
println!("Completions: {:?}", result.values);
Sourcepub async fn complete_prompt(
&mut self,
prompt_name: &str,
argument_name: &str,
argument_value: &str,
context: Option<CompletionContext>,
) -> Result<CompletionResponse>
pub async fn complete_prompt( &mut self, prompt_name: &str, argument_name: &str, argument_value: &str, context: Option<CompletionContext>, ) -> Result<CompletionResponse>
Complete a prompt argument with full MCP protocol support
This method provides access to the complete MCP completion protocol, allowing specification of argument names, prompt references, and context.
§Arguments
prompt_name
- Name of the prompt to complete forargument_name
- Name of the argument being completedargument_value
- Current value for completion matchingcontext
- Optional context with previously resolved arguments
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
// Complete with context
let mut context_args = HashMap::new();
context_args.insert("language".to_string(), "rust".to_string());
let context = CompletionContext { arguments: Some(context_args) };
let completions = client.complete_prompt(
"code_review",
"framework",
"tok",
Some(context)
).await?;
for completion in completions.values {
println!("Suggestion: {}", completion);
}
Sourcepub async fn complete_resource(
&mut self,
resource_uri: &str,
argument_name: &str,
argument_value: &str,
context: Option<CompletionContext>,
) -> Result<CompletionResponse>
pub async fn complete_resource( &mut self, resource_uri: &str, argument_name: &str, argument_value: &str, context: Option<CompletionContext>, ) -> Result<CompletionResponse>
Complete a resource template URI with full MCP protocol support
This method provides completion for resource template URIs, allowing servers to suggest values for URI template variables.
§Arguments
resource_uri
- Resource template URI (e.g., “/files/{path}”)argument_name
- Name of the argument being completedargument_value
- Current value for completion matchingcontext
- Optional context with previously resolved arguments
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
let completions = client.complete_resource(
"/files/{path}",
"path",
"/home/user/doc",
None
).await?;
for completion in completions.values {
println!("Path suggestion: {}", completion);
}
Sourcepub async fn list_resources(&mut self) -> Result<Vec<String>>
pub async fn list_resources(&mut self) -> Result<Vec<String>>
List available resources from the server
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
let resources = client.list_resources().await?;
for resource in resources {
println!("Available resource: {}", resource);
}
Sourcepub async fn ping(&mut self) -> Result<PingResult>
pub async fn ping(&mut self) -> Result<PingResult>
Send a ping request to check server health and connectivity
Sends a ping request to the server to verify the connection is active and the server is responding. This is useful for health checks and connection validation.
§Returns
Returns PingResult
on successful ping.
§Errors
Returns an error if:
- The client is not initialized
- The server is not responding
- The connection has failed
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
let result = client.ping().await?;
println!("Server is responding");
Sourcepub async fn read_resource(&mut self, uri: &str) -> Result<ReadResourceResult>
pub async fn read_resource(&mut self, uri: &str) -> Result<ReadResourceResult>
Read the content of a specific resource by URI
Retrieves the content of a resource identified by its URI. This allows clients to access specific files, documents, or other resources provided by the server.
§Arguments
uri
- The URI of the resource to read
§Returns
Returns ReadResourceResult
containing the resource content.
§Errors
Returns an error if:
- The client is not initialized
- The URI is invalid or empty
- The resource doesn’t exist
- Access to the resource is denied
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
let result = client.read_resource("file:///path/to/document.txt").await?;
for content in result.contents {
println!("Resource content: {:?}", content);
}
Sourcepub async fn list_prompts(&mut self) -> Result<Vec<Prompt>>
pub async fn list_prompts(&mut self) -> Result<Vec<Prompt>>
List available prompt templates from the server
Retrieves the complete list of prompt templates that the server provides, including all metadata: title, description, and argument schemas. This is the MCP-compliant implementation that provides everything needed for UI generation and dynamic form creation.
§Returns
Returns a vector of Prompt
objects containing:
name
: Programmatic identifiertitle
: Human-readable display name (optional)description
: Description of what the prompt does (optional)arguments
: Array of argument schemas with validation info (optional)
§Errors
Returns an error if:
- The client is not initialized
- The server doesn’t support prompts
- The request fails
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
let prompts = client.list_prompts().await?;
for prompt in prompts {
println!("Prompt: {} ({})", prompt.name, prompt.title.unwrap_or("No title".to_string()));
if let Some(args) = prompt.arguments {
println!(" Arguments: {:?}", args);
for arg in args {
let required = arg.required.unwrap_or(false);
println!(" - {}: {} (required: {})", arg.name,
arg.description.unwrap_or("No description".to_string()), required);
}
}
}
Sourcepub async fn get_prompt(
&mut self,
name: &str,
arguments: Option<PromptInput>,
) -> Result<GetPromptResult>
pub async fn get_prompt( &mut self, name: &str, arguments: Option<PromptInput>, ) -> Result<GetPromptResult>
Get a specific prompt template with argument support
Retrieves a specific prompt template from the server with support for parameter substitution. When arguments are provided, the server will substitute them into the prompt template using {parameter} syntax.
This is the MCP-compliant implementation that supports the full protocol specification.
§Arguments
name
- The name of the prompt to retrievearguments
- Optional parameters for template substitution
§Returns
Returns GetPromptResult
containing the prompt template with parameters substituted.
§Errors
Returns an error if:
- The client is not initialized
- The prompt name is empty
- The prompt doesn’t exist
- Required arguments are missing
- Argument types don’t match schema
- The request fails
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
// Get prompt without arguments (template form)
let template = client.get_prompt("greeting", None).await?;
println!("Template has {} messages", template.messages.len());
// Get prompt with arguments (substituted form)
let mut args = HashMap::new();
args.insert("name".to_string(), serde_json::Value::String("Alice".to_string()));
args.insert("greeting".to_string(), serde_json::Value::String("Hello".to_string()));
let result = client.get_prompt("greeting", Some(args)).await?;
println!("Generated prompt with {} messages", result.messages.len());
Sourcepub async fn list_roots(&mut self) -> Result<Vec<String>>
pub async fn list_roots(&mut self) -> Result<Vec<String>>
List available filesystem root directories
Retrieves the list of root directories that the server has access to. This is useful for understanding what parts of the filesystem are available for resource access.
§Returns
Returns a vector of root directory URIs available on the server.
§Errors
Returns an error if:
- The client is not initialized
- The server doesn’t support filesystem access
- The request fails
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
let roots = client.list_roots().await?;
for root_uri in roots {
println!("Available root: {}", root_uri);
}
Sourcepub async fn set_log_level(&mut self, level: LogLevel) -> Result<SetLevelResult>
pub async fn set_log_level(&mut self, level: LogLevel) -> Result<SetLevelResult>
Set the logging level for the server
Controls the verbosity of server logging. This allows clients to adjust the amount of log information they receive from the server.
§Arguments
level
- The desired logging level (Error, Warn, Info, Debug)
§Returns
Returns SetLevelResult
on successful level change.
§Errors
Returns an error if:
- The client is not initialized
- The server doesn’t support logging control
- The request fails
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
// Set server to debug logging
client.set_log_level(LogLevel::Debug).await?;
println!("Server logging level set to debug");
Sourcepub async fn subscribe(&mut self, uri: &str) -> Result<EmptyResult>
pub async fn subscribe(&mut self, uri: &str) -> Result<EmptyResult>
Subscribe to resource change notifications
Registers interest in receiving notifications when the specified resource changes. The server will send notifications when the resource is modified, created, or deleted.
§Arguments
uri
- The URI of the resource to monitor
§Returns
Returns EmptyResult
on successful subscription.
§Errors
Returns an error if:
- The client is not initialized
- The URI is invalid or empty
- The server doesn’t support subscriptions
- The request fails
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
// Subscribe to file changes
client.subscribe("file:///watch/directory").await?;
println!("Subscribed to resource changes");
Sourcepub async fn unsubscribe(&mut self, uri: &str) -> Result<EmptyResult>
pub async fn unsubscribe(&mut self, uri: &str) -> Result<EmptyResult>
Unsubscribe from resource change notifications
Cancels a previous subscription to resource changes. After unsubscribing, the client will no longer receive notifications for the specified resource.
§Arguments
uri
- The URI of the resource to stop monitoring
§Returns
Returns EmptyResult
on successful unsubscription.
§Errors
Returns an error if:
- The client is not initialized
- The URI is invalid or empty
- No active subscription exists for the URI
- The request fails
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
// Unsubscribe from file changes
client.unsubscribe("file:///watch/directory").await?;
println!("Unsubscribed from resource changes");
Sourcepub async fn list_resource_templates(&mut self) -> Result<Vec<String>>
pub async fn list_resource_templates(&mut self) -> Result<Vec<String>>
List available resource templates
Retrieves the list of resource templates that define URI patterns for accessing different types of resources. Templates help clients understand what resources are available and how to access them.
§Returns
Returns a vector of resource template URI patterns.
§Errors
Returns an error if:
- The client is not initialized
- The server doesn’t support resource templates
- The request fails
§Examples
let mut client = Client::new(StdioTransport::new());
client.initialize().await?;
let templates = client.list_resource_templates().await?;
for template in templates {
println!("Resource template: {}", template);
}
Sourcepub fn on_elicitation(&mut self, handler: Arc<dyn ElicitationHandler>)
pub fn on_elicitation(&mut self, handler: Arc<dyn ElicitationHandler>)
Register an elicitation handler for processing user input requests
Elicitation handlers are called when the server needs user input during operations. The handler should present the request to the user and collect their response according to the provided schema.
§Arguments
handler
- The elicitation handler implementation
§Examples
use turbomcp_client::Client;
use turbomcp_client::handlers::{ElicitationHandler, ElicitationRequest, ElicitationResponse, ElicitationAction, HandlerResult};
use turbomcp_transport::stdio::StdioTransport;
use async_trait::async_trait;
use std::sync::Arc;
use serde_json::json;
#[derive(Debug)]
struct MyElicitationHandler;
#[async_trait]
impl ElicitationHandler for MyElicitationHandler {
async fn handle_elicitation(
&self,
request: ElicitationRequest,
) -> HandlerResult<ElicitationResponse> {
Ok(ElicitationResponse {
action: ElicitationAction::Accept,
content: Some(json!({"user_input": "example"})),
})
}
}
let mut client = Client::new(StdioTransport::new());
client.on_elicitation(Arc::new(MyElicitationHandler));
Sourcepub fn on_progress(&mut self, handler: Arc<dyn ProgressHandler>)
pub fn on_progress(&mut self, handler: Arc<dyn ProgressHandler>)
Register a progress handler for processing operation progress updates
Progress handlers receive notifications about long-running server operations. This allows clients to display progress bars, status updates, or other feedback to users.
§Arguments
handler
- The progress handler implementation
§Examples
use turbomcp_client::Client;
use turbomcp_client::handlers::{ProgressHandler, ProgressNotification, HandlerResult};
use turbomcp_transport::stdio::StdioTransport;
use async_trait::async_trait;
use std::sync::Arc;
#[derive(Debug)]
struct MyProgressHandler;
#[async_trait]
impl ProgressHandler for MyProgressHandler {
async fn handle_progress(&self, notification: ProgressNotification) -> HandlerResult<()> {
println!("Progress: {:?}", notification);
Ok(())
}
}
let mut client = Client::new(StdioTransport::new());
client.on_progress(Arc::new(MyProgressHandler));
Sourcepub fn on_log(&mut self, handler: Arc<dyn LogHandler>)
pub fn on_log(&mut self, handler: Arc<dyn LogHandler>)
Register a log handler for processing server log messages
Log handlers receive log messages from the server and can route them to the client’s logging system. This is useful for debugging and maintaining a unified log across client and server.
§Arguments
handler
- The log handler implementation
§Examples
use turbomcp_client::Client;
use turbomcp_client::handlers::{LogHandler, LogMessage, HandlerResult};
use turbomcp_transport::stdio::StdioTransport;
use async_trait::async_trait;
use std::sync::Arc;
#[derive(Debug)]
struct MyLogHandler;
#[async_trait]
impl LogHandler for MyLogHandler {
async fn handle_log(&self, log: LogMessage) -> HandlerResult<()> {
println!("Server log: {}", log.message);
Ok(())
}
}
let mut client = Client::new(StdioTransport::new());
client.on_log(Arc::new(MyLogHandler));
Sourcepub fn on_resource_update(&mut self, handler: Arc<dyn ResourceUpdateHandler>)
pub fn on_resource_update(&mut self, handler: Arc<dyn ResourceUpdateHandler>)
Register a resource update handler for processing resource change notifications
Resource update handlers receive notifications when subscribed resources change on the server. This enables reactive updates to cached data or UI refreshes when server-side resources change.
§Arguments
handler
- The resource update handler implementation
§Examples
use turbomcp_client::Client;
use turbomcp_client::handlers::{ResourceUpdateHandler, ResourceUpdateNotification, HandlerResult};
use turbomcp_transport::stdio::StdioTransport;
use async_trait::async_trait;
use std::sync::Arc;
#[derive(Debug)]
struct MyResourceUpdateHandler;
#[async_trait]
impl ResourceUpdateHandler for MyResourceUpdateHandler {
async fn handle_resource_update(
&self,
notification: ResourceUpdateNotification,
) -> HandlerResult<()> {
println!("Resource updated: {}", notification.uri);
Ok(())
}
}
let mut client = Client::new(StdioTransport::new());
client.on_resource_update(Arc::new(MyResourceUpdateHandler));
Sourcepub fn has_elicitation_handler(&self) -> bool
pub fn has_elicitation_handler(&self) -> bool
Check if an elicitation handler is registered
Sourcepub fn has_progress_handler(&self) -> bool
pub fn has_progress_handler(&self) -> bool
Check if a progress handler is registered
Sourcepub fn has_log_handler(&self) -> bool
pub fn has_log_handler(&self) -> bool
Check if a log handler is registered
Sourcepub fn has_resource_update_handler(&self) -> bool
pub fn has_resource_update_handler(&self) -> bool
Check if a resource update handler is registered
Sourcepub fn capabilities(&self) -> &ClientCapabilities
pub fn capabilities(&self) -> &ClientCapabilities
Get the client’s capabilities configuration
Sourcepub async fn register_plugin(
&mut self,
plugin: Arc<dyn ClientPlugin>,
) -> Result<()>
pub async fn register_plugin( &mut self, plugin: Arc<dyn ClientPlugin>, ) -> Result<()>
Sourcepub fn has_plugin(&self, name: &str) -> bool
pub fn has_plugin(&self, name: &str) -> bool
Sourcepub fn get_plugin(&self, name: &str) -> Option<Arc<dyn ClientPlugin>>
pub fn get_plugin(&self, name: &str) -> Option<Arc<dyn ClientPlugin>>
Sourcepub async fn initialize_plugins(&mut self) -> Result<()>
pub async fn initialize_plugins(&mut self) -> Result<()>
Initialize all registered plugins
This should be called after registration but before using the client.
Sourcepub async fn cleanup_plugins(&mut self) -> Result<()>
pub async fn cleanup_plugins(&mut self) -> Result<()>
Cleanup all registered plugins
This should be called when the client is being shut down.