Client

Struct Client 

Source
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>

Source

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);
Source

pub fn with_capabilities(transport: T, capabilities: ClientCapabilities) -> Self

Create a new client with custom capabilities

§Arguments
  • transport - The transport implementation to use
  • capabilities - 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);
Source

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));
Source

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);
        }
    }
});
Source

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);
Source

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;
}
Source

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);
}
Source

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 call
  • arguments - 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);
Source

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 name
  • argument_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);
Source

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 for
  • argument_name - Name of the argument being completed
  • argument_value - Current value for completion matching
  • context - 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);
}
Source

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 completed
  • argument_value - Current value for completion matching
  • context - 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);
}
Source

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);
}
Source

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");
Source

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);
}
Source

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 identifier
  • title: 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);
        }
    }
}
Source

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 retrieve
  • arguments - 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());
Source

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);
}
Source

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");
Source

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");
Source

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");
Source

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);
}
Source

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));
Source

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));
Source

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));
Source

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));
Source

pub fn has_elicitation_handler(&self) -> bool

Check if an elicitation handler is registered

Source

pub fn has_progress_handler(&self) -> bool

Check if a progress handler is registered

Source

pub fn has_log_handler(&self) -> bool

Check if a log handler is registered

Source

pub fn has_resource_update_handler(&self) -> bool

Check if a resource update handler is registered

Source

pub fn capabilities(&self) -> &ClientCapabilities

Get the client’s capabilities configuration

Source

pub async fn register_plugin( &mut self, plugin: Arc<dyn ClientPlugin>, ) -> Result<()>

Register a plugin with the client

§Arguments
  • plugin - The plugin to register
§Examples
use turbomcp_client::plugins::{MetricsPlugin, PluginConfig};
use std::sync::Arc;

let metrics_plugin = Arc::new(MetricsPlugin::new(PluginConfig::Metrics));
client.register_plugin(metrics_plugin).await?;
Source

pub fn has_plugin(&self, name: &str) -> bool

Check if a plugin is registered

§Arguments
  • name - The name of the plugin to check
Source

pub fn get_plugin(&self, name: &str) -> Option<Arc<dyn ClientPlugin>>

Get plugin data for a specific plugin type

§Arguments
  • name - The name of the plugin
§Examples
use turbomcp_client::plugins::MetricsPlugin;

if let Some(plugin) = client.get_plugin("metrics") {
    // Use plugin data
}
Source

pub async fn initialize_plugins(&mut self) -> Result<()>

Initialize all registered plugins

This should be called after registration but before using the client.

Source

pub async fn cleanup_plugins(&mut self) -> Result<()>

Cleanup all registered plugins

This should be called when the client is being shut down.

Trait Implementations§

Source§

impl<T: Debug + Transport> Debug for Client<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<T> !Freeze for Client<T>

§

impl<T> !RefUnwindSafe for Client<T>

§

impl<T> Send for Client<T>

§

impl<T> Sync for Client<T>

§

impl<T> Unpin for Client<T>
where T: Unpin,

§

impl<T> !UnwindSafe for Client<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more