pub struct McpClient { /* private fields */ }Expand description
MCP client with a background message loop.
Unlike previous versions, this type is not generic over the transport.
The transport is consumed during connect() and moved
into a background Tokio task that handles message multiplexing.
All public methods take &self, enabling concurrent use from multiple
tasks.
§Construction
use tower_mcp::client::{McpClient, StdioClientTransport};
// Simple: no handler for server-initiated requests
let transport = StdioClientTransport::spawn("server", &[]).await?;
let client = McpClient::connect(transport).await?;
// With configuration
use tower_mcp::protocol::Root;
let transport = StdioClientTransport::spawn("server", &[]).await?;
let client = McpClient::builder()
.with_roots(vec![Root::new("file:///project")])
.connect_simple(transport)
.await?;Implementations§
Source§impl McpClient
impl McpClient
Sourcepub async fn connect<T: ClientTransport>(transport: T) -> Result<Self>
pub async fn connect<T: ClientTransport>(transport: T) -> Result<Self>
Connect with default settings and no handler.
Shorthand for McpClient::builder().connect_simple(transport).
Sourcepub async fn connect_with_handler<T, H>(
transport: T,
handler: H,
) -> Result<Self>where
T: ClientTransport,
H: ClientHandler,
pub async fn connect_with_handler<T, H>(
transport: T,
handler: H,
) -> Result<Self>where
T: ClientTransport,
H: ClientHandler,
Connect with a handler for server-initiated requests.
Sourcepub fn builder() -> McpClientBuilder
pub fn builder() -> McpClientBuilder
Create a builder for advanced configuration.
Sourcepub fn is_initialized(&self) -> bool
pub fn is_initialized(&self) -> bool
Check if the client has been initialized.
Sourcepub fn is_connected(&self) -> bool
pub fn is_connected(&self) -> bool
Check if the transport is still connected.
Sourcepub async fn server_info(&self) -> Option<InitializeResult>
pub async fn server_info(&self) -> Option<InitializeResult>
Get the server info (available after initialization).
Sourcepub fn protocol_support(&self) -> &ProtocolSupport
pub fn protocol_support(&self) -> &ProtocolSupport
Return the exact ordered protocol implementations enabled for this client.
Sourcepub async fn clear_response_cache(&self)
pub async fn clear_response_cache(&self)
Clear every cached final-protocol response held by this client.
Sourcepub async fn set_cache_partition(&self, partition: impl Into<String>)
pub async fn set_cache_partition(&self, partition: impl Into<String>)
Change the authorization-context partition used for private responses.
Previously cached private entries become inaccessible, while public entries remain reusable. Call this before issuing requests after the authenticated principal changes.
Sourcepub async fn response_cache_len(&self) -> usize
pub async fn response_cache_len(&self) -> usize
Return the number of response-cache entries held by this client.
Sourcepub async fn discovery(&self) -> Option<DiscoverResult>
pub async fn discovery(&self) -> Option<DiscoverResult>
Get the server discovery result after the final lifecycle is active.
Sourcepub async fn selected_protocol_version(&self) -> Option<String>
pub async fn selected_protocol_version(&self) -> Option<String>
Get the protocol version selected for the discover-based lifecycle.
Sourcepub fn server_info_blocking(&self) -> Option<InitializeResult>
pub fn server_info_blocking(&self) -> Option<InitializeResult>
Get the server info synchronously (best-effort, non-blocking).
Returns None if the lock is currently held by a writer or if
initialization hasn’t completed. Prefer server_info()
in async contexts.
Sourcepub async fn initialize(
&self,
client_name: &str,
client_version: &str,
) -> Result<InitializeResult>
pub async fn initialize( &self, client_name: &str, client_version: &str, ) -> Result<InitializeResult>
Initialize the MCP connection.
Sends the initialize request and notifications/initialized notification.
Must be called before any other operations.
Sourcepub async fn discover(
&self,
client_name: &str,
client_version: &str,
) -> Result<DiscoverResult>
pub async fn discover( &self, client_name: &str, client_version: &str, ) -> Result<DiscoverResult>
Start the sessionless 2026-07-28 lifecycle with server/discover.
This path is available only when the final implementation was compiled.
The client sends required per-request metadata from the first request,
retries one Unsupported protocol version response using the server’s
advertised intersection, and then repeats the selected version,
capabilities, and client identity on every subsequent request.
Sourcepub async fn list_tools(&self) -> Result<ListToolsResult>
pub async fn list_tools(&self) -> Result<ListToolsResult>
List available tools.
Sourcepub async fn call_tool(
&self,
name: &str,
arguments: Value,
) -> Result<CallToolResult>
pub async fn call_tool( &self, name: &str, arguments: Value, ) -> Result<CallToolResult>
Call a tool.
On the final lifecycle, a header mismatch, method-not-found, or
invalid-params response can indicate that the cached tool schema is
stale. The client invalidates tools/list, refreshes it, and retries
the rejected round once. These errors are raised before tool execution,
so the bounded retry does not replay a completed side effect.
Sourcepub async fn call_tool_once(
&self,
name: &str,
arguments: Value,
input_responses: Option<InputResponses>,
request_state: Option<String>,
) -> Result<RequestOutcome<CallToolResult>>
pub async fn call_tool_once( &self, name: &str, arguments: Value, input_responses: Option<InputResponses>, request_state: Option<String>, ) -> Result<RequestOutcome<CallToolResult>>
Send one tools/call attempt without automatically following MRTR input.
Sourcepub async fn call_tool_once_task_aware(
&self,
name: &str,
arguments: Value,
input_responses: Option<InputResponses>,
request_state: Option<String>,
) -> Result<TaskAwareCallToolOutcome>
pub async fn call_tool_once_task_aware( &self, name: &str, arguments: Value, input_responses: Option<InputResponses>, request_state: Option<String>, ) -> Result<TaskAwareCallToolOutcome>
Send one tools/call attempt and preserve a server-created task.
Unlike call_tool, this does not poll a task or
automatically fulfil input requests. Final-protocol callers can use it
to retain the exact task handle returned from the ordinary request.
Sourcepub async fn call_tool_as_task(
&self,
name: &str,
arguments: Value,
ttl_ms: Option<u64>,
) -> Result<CreateTaskResult>
pub async fn call_tool_as_task( &self, name: &str, arguments: Value, ttl_ms: Option<u64>, ) -> Result<CreateTaskResult>
Request direct control of a tool task lifecycle.
Instead of blocking until the tool finishes, the server creates a
task and immediately returns a CreateTaskResult carrying the task
id. Poll with task_get or block with
task_wait; a completed task’s result field
carries the CallToolResult the synchronous call would have
returned.
On 2025-11-25, ttl_ms is sent in the legacy task-augmentation field.
On 2026-07-28, task creation is server-directed: this sends an ordinary
request and requires the server to elect a task. A final client cannot
request a TTL, so a non-None ttl_ms is rejected on that lifecycle.
Sourcepub async fn task_get(&self, task_id: &str) -> Result<TaskObject>
pub async fn task_get(&self, task_id: &str) -> Result<TaskObject>
Fetch a task’s current state via tasks/get (SEP-2663).
For completed tasks the returned object carries the terminal
CallToolResult in its result field; for failed tasks the
JSON-RPC error is in error. Unknown or expired task ids surface as
an invalid-params error from the server.
Sourcepub async fn task_get_detailed(&self, task_id: &str) -> Result<GetTaskResult>
pub async fn task_get_detailed(&self, task_id: &str) -> Result<GetTaskResult>
Fetch the exact final-protocol tasks/get result.
This preserves status-specific payloads, including all outstanding
inputRequests. It is available only after selecting the 2026-07-28
lifecycle; legacy callers should use task_get.
Sourcepub async fn task_cancel(
&self,
task_id: &str,
reason: Option<String>,
) -> Result<()>
pub async fn task_cancel( &self, task_id: &str, reason: Option<String>, ) -> Result<()>
Cancel a task via tasks/cancel (SEP-2663).
Cancellation is cooperative: the acknowledgment is an empty result
and the observable status may remain non-terminal for a while after
the ack; poll task_get to observe the terminal
state. reason is a legacy-only field and is omitted on the final
protocol. The ack body is discarded, so legacy peers that return the
task object are also tolerated.
Sourcepub async fn task_update(
&self,
task_id: &str,
input_responses: InputResponses,
) -> Result<()>
pub async fn task_update( &self, task_id: &str, input_responses: InputResponses, ) -> Result<()>
Answer a task’s outstanding input requests via tasks/update
(SEP-2663).
Responses are matched to outstanding requests by key. Final-protocol
callers read the keys from the inputRequests of an input_required
task returned by task_get_detailed.
A partial map is valid and expected: requests left unanswered stay
outstanding and the task remains input_required until every one is
answered. Keys the server does not currently have outstanding, whether
unknown, already answered, or superseded by a later request, are
ignored rather than rejected, so replaying a stale update is safe.
The acknowledgment carries no data and is discarded. Poll
task_get to observe the resulting state.
Sourcepub async fn task_wait(&self, task_id: &str) -> Result<TaskObject>
pub async fn task_wait(&self, task_id: &str) -> Result<TaskObject>
Poll tasks/get until the task reaches a terminal state.
Honors the server’s suggested polling interval (default 1000 ms,
clamped to 50 ms..30 s). On the final protocol it also fulfils
input_required requests through the registered client handlers. A
task purged after its TTL surfaces as the server’s task-not-found
error. Wrap in
tokio::time::timeout to bound the overall wait.
Sourcepub async fn list_resources(&self) -> Result<ListResourcesResult>
pub async fn list_resources(&self) -> Result<ListResourcesResult>
List available resources.
Sourcepub async fn read_resource(&self, uri: &str) -> Result<ReadResourceResult>
pub async fn read_resource(&self, uri: &str) -> Result<ReadResourceResult>
Read a resource.
Sourcepub async fn read_resource_once(
&self,
uri: &str,
input_responses: Option<InputResponses>,
request_state: Option<String>,
) -> Result<RequestOutcome<ReadResourceResult>>
pub async fn read_resource_once( &self, uri: &str, input_responses: Option<InputResponses>, request_state: Option<String>, ) -> Result<RequestOutcome<ReadResourceResult>>
Send one resources/read attempt without automatically following MRTR.
Sourcepub async fn listen_subscriptions(
&self,
notifications: SubscriptionFilter,
) -> Result<SubscriptionHandle>
pub async fn listen_subscriptions( &self, notifications: SubscriptionFilter, ) -> Result<SubscriptionHandle>
Open a final-protocol subscriptions/listen notification stream.
The returned handle owns the long-lived request. Use
SubscriptionHandle::acknowledged to inspect the subset accepted by
the server, SubscriptionHandle::wait to observe graceful server
closure, or SubscriptionHandle::cancel to close the stream.
Notifications continue to flow through the configured
ClientHandler and carry their subscription ID in
ServerNotification::Subscription.
Sourcepub async fn subscribe_resource(&self, uri: &str) -> Result<()>
pub async fn subscribe_resource(&self, uri: &str) -> Result<()>
Subscribe to notifications/resources/updated for one resource
(resources/subscribe).
The updates themselves arrive through the notification handler, so a
client that subscribes without registering
NotificationHandler::on_resource_updated will not see them. Servers
that support this advertise resources.subscribe in their
capabilities; one that does not will reject the request.
Sourcepub async fn unsubscribe_resource(&self, uri: &str) -> Result<()>
pub async fn unsubscribe_resource(&self, uri: &str) -> Result<()>
Stop receiving updates for a resource (resources/unsubscribe).
Sourcepub async fn list_prompts(&self) -> Result<ListPromptsResult>
pub async fn list_prompts(&self) -> Result<ListPromptsResult>
List available prompts.
Sourcepub async fn list_tools_with_cursor(
&self,
cursor: Option<String>,
) -> Result<ListToolsResult>
pub async fn list_tools_with_cursor( &self, cursor: Option<String>, ) -> Result<ListToolsResult>
List tools with an optional pagination cursor.
Sourcepub async fn list_resources_with_cursor(
&self,
cursor: Option<String>,
) -> Result<ListResourcesResult>
pub async fn list_resources_with_cursor( &self, cursor: Option<String>, ) -> Result<ListResourcesResult>
List resources with an optional pagination cursor.
Sourcepub async fn list_resource_templates(
&self,
) -> Result<ListResourceTemplatesResult>
pub async fn list_resource_templates( &self, ) -> Result<ListResourceTemplatesResult>
List resource templates.
Sourcepub async fn list_resource_templates_with_cursor(
&self,
cursor: Option<String>,
) -> Result<ListResourceTemplatesResult>
pub async fn list_resource_templates_with_cursor( &self, cursor: Option<String>, ) -> Result<ListResourceTemplatesResult>
List resource templates with an optional pagination cursor.
Sourcepub async fn list_prompts_with_cursor(
&self,
cursor: Option<String>,
) -> Result<ListPromptsResult>
pub async fn list_prompts_with_cursor( &self, cursor: Option<String>, ) -> Result<ListPromptsResult>
List prompts with an optional pagination cursor.
Sourcepub async fn list_all_tools(&self) -> Result<Vec<ToolDefinition>>
pub async fn list_all_tools(&self) -> Result<Vec<ToolDefinition>>
List all tools, following pagination cursors until exhausted.
Sourcepub async fn list_all_resources(&self) -> Result<Vec<ResourceDefinition>>
pub async fn list_all_resources(&self) -> Result<Vec<ResourceDefinition>>
List all resources, following pagination cursors until exhausted.
Sourcepub async fn list_all_resource_templates(
&self,
) -> Result<Vec<ResourceTemplateDefinition>>
pub async fn list_all_resource_templates( &self, ) -> Result<Vec<ResourceTemplateDefinition>>
List all resource templates, following pagination cursors until exhausted.
Sourcepub async fn list_all_prompts(&self) -> Result<Vec<PromptDefinition>>
pub async fn list_all_prompts(&self) -> Result<Vec<PromptDefinition>>
List all prompts, following pagination cursors until exhausted.
Sourcepub async fn call_tool_text(
&self,
name: &str,
arguments: Value,
) -> Result<String>
pub async fn call_tool_text( &self, name: &str, arguments: Value, ) -> Result<String>
Call a tool and return the concatenated text content.
Returns the text from all Text items joined together.
If the tool result indicates an error (is_error is true), returns
an error with the text content as the message.
For more control over the result, use call_tool().
Sourcepub async fn get_prompt(
&self,
name: &str,
arguments: Option<HashMap<String, String>>,
) -> Result<GetPromptResult>
pub async fn get_prompt( &self, name: &str, arguments: Option<HashMap<String, String>>, ) -> Result<GetPromptResult>
Get a prompt.
Sourcepub async fn get_prompt_once(
&self,
name: &str,
arguments: HashMap<String, String>,
input_responses: Option<InputResponses>,
request_state: Option<String>,
) -> Result<RequestOutcome<GetPromptResult>>
pub async fn get_prompt_once( &self, name: &str, arguments: HashMap<String, String>, input_responses: Option<InputResponses>, request_state: Option<String>, ) -> Result<RequestOutcome<GetPromptResult>>
Send one prompts/get attempt without automatically following MRTR.
Sourcepub async fn complete(
&self,
reference: CompletionReference,
argument_name: &str,
argument_value: &str,
) -> Result<CompleteResult>
pub async fn complete( &self, reference: CompletionReference, argument_name: &str, argument_value: &str, ) -> Result<CompleteResult>
Request completion suggestions from the server.
Sourcepub async fn complete_prompt_arg(
&self,
prompt_name: &str,
argument_name: &str,
argument_value: &str,
) -> Result<CompleteResult>
pub async fn complete_prompt_arg( &self, prompt_name: &str, argument_name: &str, argument_value: &str, ) -> Result<CompleteResult>
Request completion for a prompt argument.
Sourcepub async fn complete_resource_uri(
&self,
resource_uri: &str,
argument_name: &str,
argument_value: &str,
) -> Result<CompleteResult>
pub async fn complete_resource_uri( &self, resource_uri: &str, argument_name: &str, argument_value: &str, ) -> Result<CompleteResult>
Request completion for a resource URI.
Sourcepub async fn request<P: Serialize, R: DeserializeOwned>(
&self,
method: &str,
params: &P,
) -> Result<R>
pub async fn request<P: Serialize, R: DeserializeOwned>( &self, method: &str, params: &P, ) -> Result<R>
Send a raw typed request to the server.
Sourcepub async fn notify<P: Serialize>(&self, method: &str, params: &P) -> Result<()>
pub async fn notify<P: Serialize>(&self, method: &str, params: &P) -> Result<()>
Send a raw typed notification to the server.
Sourcepub async fn set_roots(&self, roots: Vec<Root>) -> Result<()>
pub async fn set_roots(&self, roots: Vec<Root>) -> Result<()>
Set roots and notify the server if initialized.
Sourcepub async fn add_root(&self, root: Root) -> Result<()>
pub async fn add_root(&self, root: Root) -> Result<()>
Add a root and notify the server if initialized.
Sourcepub async fn remove_root(&self, uri: &str) -> Result<bool>
pub async fn remove_root(&self, uri: &str) -> Result<bool>
Remove a root by URI and notify the server if initialized.
Sourcepub async fn list_roots(&self) -> ListRootsResult
pub async fn list_roots(&self) -> ListRootsResult
Get the roots list result (for responding to server’s roots/list request).