Skip to main content

Client

Struct Client 

Source
pub struct Client<T: Transport> { /* private fields */ }
Expand description

MCP client for connecting to servers.

Implementations§

Source§

impl<T: Transport> Client<T>

Source

pub fn new(transport: T) -> Self

Create a new client with the given transport.

Uses default client information with the name “pmcp-client” and the current crate version.

§Examples
use pmcp::{Client, StdioTransport};

let transport = StdioTransport::new();
let client = Client::new(transport);
Source

pub fn with_info(transport: T, client_info: Implementation) -> Self

Create a new client with custom info.

Allows specifying custom client name and version information that will be sent to the server during initialization.

§Examples
use pmcp::{Client, StdioTransport, Implementation};

let transport = StdioTransport::new();
let client_info = Implementation::new("my-custom-client", "2.1.0");
let client = Client::with_info(transport, client_info);
Source

pub fn with_options( transport: T, client_info: Implementation, options: ProtocolOptions, ) -> Self

Create a new client with custom protocol options.

§Examples
use pmcp::{Client, StdioTransport, Implementation};
use pmcp::shared::ProtocolOptions;

// Custom options for high-throughput scenarios
let options = ProtocolOptions {
    enforce_strict_capabilities: false,
    debounced_notification_methods: vec![
        "notifications/progress".to_string(),
        "notifications/message".to_string(),
    ],
};

let transport = StdioTransport::new();
let client_info = Implementation::new("high-throughput-client", "1.0.0");

let client = Client::with_options(transport, client_info, options);
Source

pub fn with_client_options(transport: T, options: ClientOptions) -> Self

Construct a client with caller-supplied ClientOptions.

Mirrors Self::new but wires in a ClientOptions value so that Self::list_all_tools / Self::list_all_prompts / etc. honour a custom max_iterations cap.

§ClientBuilder parity

ClientBuilder does not currently expose a .client_options() setter. If you need a custom ClientOptions, construct the client via Self::with_client_options directly.

§Examples
use pmcp::{Client, ClientOptions};

let opts = ClientOptions::default().with_max_iterations(50);
let _client = Client::with_client_options(transport, opts);
Source

pub async fn initialize( &mut self, capabilities: ClientCapabilities, ) -> Result<InitializeResult>

Initialize the connection with the server.

Performs the MCP initialization handshake, negotiating capabilities and receiving server information. This must be called before using other client methods.

§Host capabilities are registry-derived (sampling / elicitation / roots)

The three host-side capability fields — sampling, elicitation, and roots — are derived from the handlers registered on ClientBuilder, not from the value passed here. If no matching host handler is registered, the corresponding field is forced to None on the wire even when the caller set it (the anti-capability-lie rule: a client must not advertise a host capability it cannot service). Register handlers via ClientBuilder::on_sampling, ClientBuilder::on_elicitation, and ClientBuilder::on_roots to advertise these capabilities. When a handler is registered, any caller-configured detail for that field (e.g. roots.list_changed) is preserved. All other capability fields (tasks, experimental, …) pass through unchanged.

§Examples
use pmcp::{Client, StdioTransport, ClientCapabilities};

let transport = StdioTransport::new();
let mut client = Client::new(transport);

let capabilities = ClientCapabilities::default();
let server_info = client.initialize(capabilities).await?;

println!("Server: {} v{}",
         server_info.server_info.name,
         server_info.server_info.version);
§Severability: this method is NOT gated, and that is measured

SMPL-01 names “initialize/session lifecycle” as v1-only machinery that a full-v2 build must not carry. Plan 117-14 MEASURED whether #[cfg(feature = "v1-compat")] could be applied here and took a documented fallback for two reasons, both recorded in .planning/phases/117-agents-tester-v1-severability/117-14-SUMMARY.md:

  1. It is DUAL-era, not v1-only. The is_v2() branch below is a deliberate Phase-113 compatibility affordance — it sends nothing and exists so v1-shaped application code keeps compiling after opting into v2. Gating this method would delete v2 behaviour, not just v1 behaviour.
  2. src/composition/mcp_client.rs calls it, and composition is in the full-v2 feature list. Propagating the gate there would mean a composition connection that reports itself initialized without ever having handshaken — a semantic change to a subsystem this plan has no mandate over.

SMPL-01’s “initialize” clause is therefore met on the SERVER side only, and even there it is the session BOOKKEEPING that is severed, not the handshake: plan 117-12 moved process_init_session, update_session_after_init and the rest of the session-lifecycle functions into v1_session.rs, while a full-v2 server still answers an initialize POST statelessly (only GET and DELETE are refused 405). The pure classifiers is_initialize_request / extract_negotiated_version therefore stay ungated in streamable_http_server.rs. docs/v1-sunset-policy.md MUST name this as a known limitation.

§Errors

Returns an error if:

  • The client is already initialized
  • The server rejects the initialization
  • Communication with the server fails
Source

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

Ask a v2 server for its capability projection (server/discover).

v2 has no initialize, so this is how a client learns what the server supports. It is EXPLICIT: pmcp never calls it implicitly, and never uses it to CHOOSE an era (Phase-113 D-08 forbids exactly that auto-probe). Populating capabilities from a call the USER made is a different thing from probing to decide which protocol to speak — do not “restore” the latter.

Takes &mut self because it STORES the returned capabilities: after this call Self::assert_capability enforces on v2 exactly as it does on v1 against initialize-learned ones.

§Errors

Returns an error when the connection did not opt into 2026-07-28 (server/discover does not exist on v1 — a v1 server answers -32601), when the transport fails, or when the server returns a JSON-RPC error.

Source

pub fn get_server_capabilities(&self) -> Option<&ServerCapabilities>

Get server capabilities after initialization.

Source

pub fn get_server_version(&self) -> Option<&Implementation>

Get server version information after initialization.

Source

pub fn get_instructions(&self) -> Option<&str>

Get server instructions after initialization.

Source

pub async fn ping(&self) -> Result<()>

Send a ping to the server.

Source

pub async fn set_logging_level(&self, level: LoggingLevel) -> Result<()>

Set the logging level on the server.

Source

pub async fn list_tools( &self, cursor: Option<String>, ) -> Result<ListToolsResult>

List available tools.

Retrieves information about all tools available on the server, including their names, descriptions, and input schemas.

§Examples
use pmcp::{Client, StdioTransport, ClientCapabilities};

let transport = StdioTransport::new();
let mut client = Client::new(transport);
client.initialize(ClientCapabilities::default()).await?;

// List all tools
let tools = client.list_tools(None).await?;
for tool in tools.tools {
    println!("Tool: {} - {}",
             tool.name,
             tool.description.unwrap_or_else(|| "No description".to_string()));
}
§Arguments
  • cursor - Optional pagination cursor for retrieving additional results
Source

pub async fn call_tool( &self, name: String, arguments: Value, ) -> Result<CallToolResult>

Call a tool.

Invokes a server-provided tool with the specified name and arguments. The server must have declared the tool via the tools capability during initialization.

§Arguments
  • name - The name of the tool to call
  • arguments - JSON value containing the tool’s arguments
§Examples
use pmcp::{Client, StdioTransport, ClientCapabilities};
use serde_json::json;

let transport = StdioTransport::new();
let mut client = Client::new(transport);
client.initialize(ClientCapabilities::default()).await?;

// Call a simple tool with no arguments
let result = client.call_tool(
    "list_files".to_string(),
    json!({})
).await?;

// Call a tool with specific arguments
let search_result = client.call_tool(
    "search".to_string(),
    json!({
        "query": "rust programming",
        "limit": 10
    })
).await?;

// Tools can return structured data
if let Some(content) = result.content.first() {
    match content {
        pmcp::Content::Text { text } => {
            println!("Tool result: {}", text);
        }
        _ => println!("Non-text tool result"),
    }
}
§Errors

Returns an error if:

  • The client is not initialized
  • The server doesn’t support tools
  • The tool name doesn’t exist
  • The arguments are invalid for the tool
  • Network or protocol errors occur
§v2 (2026-07-28) behavior

On a connection that opted into 2026-07-28, this method auto-orchestrates Multi-Round-Trip Elicitation: an input_required result is answered from the registered host handlers and the request is resent, up to ClientBuilder::mrtr_round_limit rounds.

Two v2-only error outcomes are therefore possible, both programmatically distinguishable:

On v1 this method is byte-identical to every prior release.

Source

pub async fn call_tool_with_task( &self, name: String, arguments: Value, ) -> Result<ToolCallResponse>

Call a tool with task augmentation.

Sends a tools/call request with the task field set, signaling to the server that this client supports async task polling. The server may return either a CreateTaskResult (async task created) or a CallToolResult (sync result) depending on the tool’s taskSupport declaration.

Use call_tool instead if you don’t need task support.

§Returns
  • Ok(ToolCallResponse::Task(task)) if the server created an async task. Poll with tasks_get until the task reaches a terminal status.
  • Ok(ToolCallResponse::Result(result)) if the server returned the result synchronously.
Source

pub async fn call_tool_with_task_and_meta( &self, name: String, arguments: Value, meta: RequestMeta, ) -> Result<ToolCallResponse>

Call a tool with task augmentation AND custom request _meta.

Identical to call_tool_with_task except the request carries the supplied RequestMeta as _meta, so namespaced/guard state (attached via RequestMeta::with_meta) travels alongside the task augmentation in a single tools/call.

Passing an empty RequestMeta behaves like call_tool_with_task.

§Returns
  • Ok(ToolCallResponse::Task(task)) if the server created an async task.
  • Ok(ToolCallResponse::Result(result)) if the server returned the result synchronously.
§Errors

Returns an error if the client is not initialized, the server does not support tools, or a network/protocol error occurs.

§Example
let meta = RequestMeta::new()
    .with_meta("io.modelcontextprotocol/related-task", serde_json::json!({"taskId": "t-1"}));
let resp = client
    .call_tool_with_task_and_meta("member".to_string(), serde_json::json!({}), meta)
    .await?;
Source

pub async fn call_tool_with_meta( &self, name: String, arguments: Value, meta: RequestMeta, ) -> Result<CallToolResult>

Call a tool (non-task) with custom request _meta.

Identical to call_tool except the request carries the supplied RequestMeta as _meta. Namespaced/guard state travels via RequestMeta::with_meta and is visible to the server tool handler through extra.request_meta.

Passing an empty RequestMeta behaves like call_tool.

§Errors

Returns an error if the client is not initialized, the server does not support tools, the tool name does not exist, or a network/protocol error occurs.

§Example
let meta = RequestMeta::new().with_meta("x-pmcp-team-depth", serde_json::json!(1));
let result = client
    .call_tool_with_meta("echo".to_string(), serde_json::json!({}), meta)
    .await?;
Source

pub async fn tasks_get(&self, task_id: &str) -> Result<Task>

Get the current status of a task.

Polls the server for the task’s current state. Call this repeatedly (respecting task.poll_interval) until the task reaches a terminal status (Completed, Failed, or Cancelled).

§Era awareness (Phase 114, plan 19)
EraWire shapeHow it becomes a Task
v1NESTED {"task": {…, "ttl", "pollInterval"}}unchanged: decode GetTaskResult, return .task
v2FLAT {taskId, status, createdAt, lastUpdatedAt, ttlMs, …}decode TaskV2, then TaskV2::to_v1

The signature is unchanged on purpose: ttlMs lands on Task::ttl and pollIntervalMs on Task::poll_interval, so an existing caller’s poll logic keeps working verbatim against a v2 server.

The v2 arm decodes only the flat BASE task, never the status-discriminated DetailedTask. That is deliberate: a backend that cannot supply a terminal task’s result degrades to the bare flat Task, and a strict decode here would turn “I could not read the detail” into “I could not read the task at all”. Use Self::tasks_get_detailed when you want the inlined detail and want a missing one to be an error.

§Errors

Returns an error if:

  • The server doesn’t support tasks
  • The task ID doesn’t exist or belongs to another owner. On v2 that is ONE -32602 answer for absent / wrong-owner / EXPIRED alike — the three are deliberately indistinguishable (no existence oracle), so a client must not try to tell them apart.
Source

pub async fn tasks_get_detailed(&self, task_id: &str) -> Result<DetailedTaskV2>

Get a task’s status TOGETHER WITH its status-conditional detail — v2 only (Phase 114, plan 19).

The additive sibling of Self::tasks_get. On 2026-07-28 a tasks/get result is a flat DetailedTask: one variant per status, each carrying exactly the key its schema variant marks required — result on completed, error on failed, inputRequests on input_required, nothing extra on working / cancelled.

This is what removes the second round trip v1 needed: tasks/result does not exist on v2 because the terminal payload is already here.

§Strict by design

DetailedTaskV2::from_wire_value is STATUS-DIRECTED: it reads status first and then REQUIRES that status’s key. A completed task with no result is an error here rather than a best-effort decode into a variant that happens to fit — the same discipline the server-side projection applies when it emits.

§Errors
Source

pub async fn tasks_result(&self, task_id: &str) -> Result<CallToolResult>

Get the final result of a completed task — v1 only.

For a task-augmented tools/call, this returns the CallToolResult that the tool would have returned synchronously. Only valid when the task status is Completed.

§RETIRED on 2026-07-28 (Phase 114, TASK-03 / D-15)

tasks/result is absent from the tasks extension: the v2 tasks/get INLINES the terminal payload, so a second round trip has nothing left to do. A v2 server answers this method -32601. Calling it on a v2 connection therefore fails LOCALLY — no bytes leave the process — with an Error::retired_on_v2 naming Self::tasks_get_detailed’s method as the replacement. A clear local error beats a round trip to an opaque method-not-found.

Source

pub async fn wait_for_task( &self, task_id: &str, opts: WaitForTaskOptions, ) -> Result<CallToolResult>

Poll a task to terminal status, then return its final result.

Drives tasks/get in a loop until TaskStatus::is_terminal, honoring the polling interval (caller override, else the task-reported pollInterval, else a built-in default) and an optional overall timeout.

§Where the terminal result comes from is ERA-SPLIT (Phase 114, plan 19)
EraTerminal step
v1a second round trip: Client::tasks_result, exactly as before
v2ZERO extra round trips — the result is INLINE in the tasks/get payload the loop already fetched

tasks/result does not exist on 2026-07-28 (a v2 server answers -32601), so the v2 arm must not call it — and does not need to, because a v2 tasks/get on a completed task carries result and on a failed task carries error. Nothing else in the loop is era-aware: the classifier, the floor, the budget clamp and the clock are shared.

On v2 a task that reaches failed surfaces its inlined JSON-RPC error as a typed client error rather than an empty success, and a cancelled task is an error too — neither has a result to return.

§Wasm safety

The delay between polls uses crate::runtime::sleep (not tokio::time::sleep directly) and the timeout is measured with web_time::Instant (not std::time::Instant, which panics on wasm32), so this compiles and runs in the browser.

§Hot-loop protection

The effective interval is clamped to a small floor (50 ms), so a zero or absent pollInterval cannot turn the loop into a busy spin.

§Errors
  • Propagates tasks/get / tasks/result transport and protocol errors.
  • Returns Error::Timeout when opts.max_poll_duration_secs elapses before the task reaches a terminal status. Each sleep is clamped to the remaining budget, so a large (possibly server-reported) poll interval cannot overshoot the caller’s budget by more than roughly the 50 ms clamp floor.
  • Returns Error::Validation when the task enters TaskStatus::InputRequired: that state is NOT terminal and needs client-side action (elicitation) this poller cannot provide, so polling on would hang forever under the default (unbounded) options. Handle the required input, then resume polling — or use Client::wait_for_task_with_inputs, which is exactly this poller with a responder attached and IS the answer to that message.
§Durable and replay consumers

Do not wrap wait_for_task inside a durable / replay workflow step. It sleeps, loops, and owns the whole polling lifecycle, which is non-deterministic under replay (each re-execution would re-sleep and re-poll). A durable consumer should instead call Task::poll_decision plus resolve_poll_interval once per tick inside its own memoized step and persist the decision between ticks — those are pure, replay-deterministic functions of the polled task, unlike this blocking poller (D-11 / D-16).

See the pmcp-book “Durable and replay consumers” section (heading ## Durable and replay consumers in pmcp-book/src/ch12-7-tasks.md) for the full per-poll pattern: https://paiml.github.io/rust-mcp-sdk/ch12-7-tasks.html#durable-and-replay-consumers. (This is a deliberate plain-text/URL reference, not a rustdoc intra-doc link, so it never fails cargo doc even before that page ships.)

§Example
use pmcp::client::WaitForTaskOptions;

// `result` came from a task-augmented tools/call.
if let Some(meta) = result.related_task() {
    let final_result = client
        .wait_for_related_task(&meta, WaitForTaskOptions::default())
        .await?;
}
Source

pub async fn wait_for_task_with_inputs<F, Fut>( &self, task_id: &str, opts: WaitForTaskOptions, responder: F, ) -> Result<CallToolResult>
where F: FnMut(InputRequests) -> Fut, Fut: Future<Output = Result<InputResponses>>,

Client::wait_for_task WITH a responder for input_required — v2 only (Phase 114, TASK-02).

The same poller, with one behaviour added: when the task pauses for input, responder is handed the task’s inputRequests (read from the tasks/get payload the loop already fetched — no extra round trip), its answers are delivered with Client::tasks_update, and polling resumes.

Everything else is Client::wait_for_task VERBATIM — the same poll_decision() classifier matched with no wildcard arm, the same MIN_POLL_MS floor, the same remaining-budget clamp, the same web_time::Instant clock — because it is literally the same function with a responder passed in.

§v2 only

tasks/update does not exist on 2026-07-28’s predecessor, so a v1 call fails LOCALLY with no bytes on the wire. Use Client::wait_for_task plus your own elicitation handling there.

§The input rounds are BOUNDED

A server that keeps re-requesting input cannot spin a client forever: the number of input_required rounds is capped by the SAME configured bound the MRTR gather->resend loop uses (ClientBuilder::mrtr_round_limit, defaulting to DEFAULT_MRTR_ROUND_LIMIT = 8). It is deliberately the same knob and not a new constant: both bound “how many times will I answer this server’s questions before I conclude it is not making progress”, and two independently-tuned answers to one question is how they drift apart. Exceeding it returns Error::mrtr_round_limit_exceeded.

§A task is NOT a higher-trust channel

The requests handed to responder are ordinary elicitation / sampling / roots requests that happen to arrive through a task. Apply the SAME consent and policy gates you would for a direct server-initiated request; this poller passes values through and executes nothing server-supplied.

§Errors

Everything Client::wait_for_task returns, plus whatever responder itself returns (propagated unchanged), plus the round-bound error above.

§Example
use pmcp::client::WaitForTaskOptions;
use pmcp::types::mrtr::InputResponses;

let result = client
    .wait_for_task_with_inputs("task-1", WaitForTaskOptions::default(), |requests| async move {
        let mut answers = InputResponses::new();
        for (key, request) in &requests {
            answers.insert(key.clone(), answer_one(request).await?);
        }
        Ok(answers)
    })
    .await?;

Poll a task referenced by TaskMetadata to terminal, then return its tasks/result — the zero-glue counterpart of Client::wait_for_task.

Any fields left unset in opts are filled from meta (WaitForTaskOptions::or_from_metadata) so a caller who holds a CallToolResult::related_task result composes without hand-copying poll fields.

§Errors

Same as Client::wait_for_task.

Source

pub async fn tasks_list( &self, cursor: Option<String>, ) -> Result<ListTasksResult>

List tasks owned by the current client — v1 only.

§RETIRED on 2026-07-28 (Phase 114, TASK-03 / D-15)

tasks/list is absent from the tasks extension, removed as a SECURITY improvement: with no enumeration primitive a server cannot inadvertently leak the existence of one caller’s tasks to another. There is no replacement method — a v2 client keeps the ids it was handed. Calling this on a v2 connection fails LOCALLY with an Error::retired_on_v2, with no bytes on the wire.

Source

pub async fn tasks_cancel(&self, task_id: &str) -> Result<Task>

Cancel a running task and report the task as the server now sees it.

§Era awareness (Phase 114, plan 19)

v1 answers a cancel with the NESTED {"task": {…}} envelope and this method returns that task, exactly as it always has.

v2’s CancelTaskResult is Result — an EMPTY acknowledgement with no task body at all (inventory row 20), so today’s CancelTaskResult decode fails outright against it. Because this method’s return type is Task and cannot change without a MAJOR semver bump, the v2 arm acknowledges the cancel through Self::tasks_cancel_ack and then performs ONE follow-up Self::tasks_get. It does NOT synthesise a Task: fabricating status: cancelled would be inventing status information the server deliberately did not send.

§Cancellation is cooperative and eventually consistent

That is the SEMANTICS of the empty ack, not a limitation of this client. The returned task MAY still be working, and MAY later settle on a terminal status other than cancelled. Callers that only need the acknowledgement — and do not want the extra round trip — should call Self::tasks_cancel_ack directly.

Source

pub async fn tasks_cancel_ack(&self, task_id: &str) -> Result<()>

Request cancellation and read only the ACKNOWLEDGEMENT (Phase 114).

The zero-invention primitive Self::tasks_cancel is built on: it accepts ANY successful result — including v2’s bare {} — and returns (). One round trip, and nothing is claimed about the task’s status.

Works on BOTH eras. On v1 the response body carries a Task which this method DISCARDS; call Self::tasks_cancel when you want it.

Cancellation is cooperative and eventually consistent: a successful acknowledgement means the request was accepted, NOT that the task has stopped.

Source

pub async fn tasks_update( &self, task_id: &str, responses: InputResponses, ) -> Result<()>

Deliver responses to a paused task’s outstanding inputRequests — v2 only (Phase 114, TASK-02).

tasks/update is how an input_required task is un-paused: each key of responses MUST correspond to a currently-outstanding inputRequests key from Self::tasks_get_detailed. The acknowledgement is EMPTY, so this returns ().

§It is sent UNTYPED, on purpose

There is no ClientRequest::TasksUpdate variant and there must not be one: ClientRequest is public and not #[non_exhaustive], so adding a variant is a MAJOR semver break. This goes out through the same raw path Self::server_discover uses.

§A task is NOT a higher-trust channel

The spec is explicit that input requests delivered through a task carry exactly the trust of the elicitation / sampling they wrap. Whatever produces responses must apply the SAME consent and policy gates it would for a direct elicitation/create; this method transmits the values and executes nothing the server supplied.

§Errors
  • Error::InvalidState on a v1 connection — tasks/update does not exist there, and NO bytes are sent.
  • Error::UnsupportedCapability (built by Error::capability) when the tasks extension was not negotiated — again with no bytes sent.
  • The server’s own JSON-RPC error otherwise (e.g. an unknown or already-answered input key).
Source

pub async fn call_tool_and_poll( &self, name: String, arguments: Value, max_polls: usize, ) -> Result<CallToolResult>

Available on non-WebAssembly only.

Call a tool and automatically poll until the task completes.

This is a high-level convenience method that encapsulates the full task lifecycle:

  1. Calls the tool with task augmentation
  2. If the server returns a task, polls tasks/get until terminal status
  3. Returns the final CallToolResult

If the server returns a sync result (no task), returns it immediately.

§Arguments
  • name - Tool name
  • arguments - Tool arguments
  • max_polls - Maximum number of poll attempts before giving up (0 = unlimited)
Source

pub async fn list_prompts( &self, cursor: Option<String>, ) -> Result<ListPromptsResult>

List available prompts.

Retrieves information about all prompts available on the server, including their names, descriptions, and required arguments.

§Arguments
  • cursor - Optional cursor for pagination of large prompt lists
§Examples
use pmcp::{Client, StdioTransport, ClientCapabilities};

let transport = StdioTransport::new();
let mut client = Client::new(transport);
client.initialize(ClientCapabilities::default()).await?;

// List all prompts
let prompts = client.list_prompts(None).await?;
for prompt in prompts.prompts {
    println!("Prompt: {} - {}",
             prompt.name,
             prompt.description.unwrap_or_else(|| "No description".to_string()));
     
    // Show required arguments
    if let Some(args) = prompt.arguments {
        for arg in args {
            println!("  - {}: {} (required: {})",
                     arg.name,
                     arg.description.unwrap_or_else(|| "No description".to_string()),
                     arg.required);
        }
    }
}
§Errors

Returns an error if:

  • The client is not initialized
  • The server doesn’t support prompts
  • Network or protocol errors occur
Source

pub async fn get_prompt( &self, name: String, arguments: HashMap<String, String>, ) -> Result<GetPromptResult>

Get a prompt.

Retrieves a specific prompt from the server with the provided arguments. The prompt is processed by the server and returned with filled-in content.

§Arguments
  • name - The name of the prompt to retrieve
  • arguments - Key-value pairs for prompt arguments
§Examples
use pmcp::{Client, StdioTransport, ClientCapabilities};
use std::collections::HashMap;

let transport = StdioTransport::new();
let mut client = Client::new(transport);
client.initialize(ClientCapabilities::default()).await?;

// Get a prompt with arguments
let mut args = HashMap::new();
args.insert("language".to_string(), "Rust".to_string());
args.insert("topic".to_string(), "async programming".to_string());

let prompt_result = client.get_prompt(
    "code_review".to_string(),
    args
).await?;

println!("Prompt description: {}",
         prompt_result.description.unwrap_or_else(|| "No description".to_string()));

// Process the prompt messages
for message in prompt_result.messages {
    println!("Role: {}", message.role);
    match &message.content {
        pmcp::Content::Text { text } => {
            println!("Content: {}", text);
        }
        _ => println!("Non-text content"),
    }
}
§Errors

Returns an error if:

  • The client is not initialized
  • The server doesn’t support prompts
  • The prompt name doesn’t exist
  • Required arguments are missing
  • Network or protocol errors occur
§v2 (2026-07-28) behavior

Auto-orchestrates MRTR exactly as Self::call_tool documents, including the Error::is_input_required_unfulfilled and Error::is_mrtr_round_limit_exceeded outcomes. See Self::get_prompt_mrtr to receive an unfulfilled input_required as a value. v1 is byte-identical to every prior release.

Source

pub async fn call_tool_typed<A: Serialize + ?Sized + Sync>( &self, name: impl Into<String> + Send, args: &A, ) -> Result<CallToolResult>

Call a tool with typed, serializable arguments.

Serializes args via serde_json::to_value and delegates to Self::call_tool. Serialization failures are mapped to Error::validation with the underlying serde error message.

§Examples
use serde::Serialize;

#[derive(Serialize)]
struct Search { query: String, limit: u32 }

let _ = client.call_tool_typed(
    "search",
    &Search { query: "rust mcp".into(), limit: 10 },
).await?;
Source

pub async fn call_tool_typed_with_task<A: Serialize + ?Sized + Sync>( &self, name: impl Into<String> + Send, args: &A, ) -> Result<ToolCallResponse>

Typed sibling of Self::call_tool_with_task.

Delegates to the two-argument Self::call_tool_with_task; there is no TaskMetadata parameter on the live client API, so none is exposed here.

§Examples
use serde::Serialize;
#[derive(Serialize)]
struct Args { file: String }
let _ = client.call_tool_typed_with_task("scan", &Args { file: "a.rs".into() }).await?;
Source

pub async fn call_tool_typed_and_poll<A: Serialize + ?Sized + Sync>( &self, name: impl Into<String> + Send, args: &A, max_polls: usize, ) -> Result<CallToolResult>

Available on non-WebAssembly only.

Typed sibling of Self::call_tool_and_poll.

Delegates to the three-argument Self::call_tool_and_poll (name, arguments, max_polls: usize). There is no poll_interval or TaskMetadata parameter on the live client API — the server-supplied poll_interval is honoured internally by call_tool_and_poll.

max_polls = 0 means unlimited polls, matching the sibling’s semantics.

§Examples
use serde::Serialize;
#[derive(Serialize)]
struct Args { job: String }
let _ = client.call_tool_typed_and_poll(
    "build",
    &Args { job: "nightly".into() },
    30, // max_polls
).await?;
Source

pub async fn get_prompt_typed<A: Serialize + ?Sized + Sync>( &self, name: impl Into<String> + Send, args: &A, ) -> Result<GetPromptResult>

Get a prompt with typed, serializable arguments.

Serializes args to a JSON object, then coerces each leaf to a String for the wire-level HashMap<String, String> arguments:

  • null entries are omitted
  • string entries pass through unchanged (no JSON-quoting)
  • number and bool entries use Display (e.g. 42, true)
  • array and object entries are re-serialized via serde_json::to_string

Non-object top-level serializations are rejected with Error::validation.

§Examples
use serde::Serialize;

#[derive(Serialize)]
struct SummaryArgs { topic: String, length: u32 }

let _ = client.get_prompt_typed(
    "summarize",
    &SummaryArgs { topic: "rust async".into(), length: 200 },
).await?;
Source

pub async fn list_resources( &self, cursor: Option<String>, ) -> Result<ListResourcesResult>

List available resources.

Retrieves information about all resources available on the server, including their names, descriptions, URIs, and MIME types.

§Arguments
  • cursor - Optional cursor for pagination of large resource lists
§Examples
use pmcp::{Client, StdioTransport, ClientCapabilities};

let transport = StdioTransport::new();
let mut client = Client::new(transport);
client.initialize(ClientCapabilities::default()).await?;

// List all resources
let resources = client.list_resources(None).await?;
for resource in resources.resources {
    println!("Resource: {} ({})", resource.name, resource.uri);
    if let Some(description) = resource.description {
        println!("  Description: {}", description);
    }
    if let Some(mime_type) = resource.mime_type {
        println!("  MIME Type: {}", mime_type);
    }
}
§Errors

Returns an error if:

  • The client is not initialized
  • The server doesn’t support resources
  • Network or protocol errors occur
Source

pub async fn list_resource_templates( &self, cursor: Option<String>, ) -> Result<ListResourceTemplatesResult>

List resource templates.

Retrieves information about all resource templates available on the server. Resource templates define patterns for dynamically generated resources.

§Arguments
  • cursor - Optional cursor for pagination of large template lists
§Examples
use pmcp::{Client, StdioTransport, ClientCapabilities};

let transport = StdioTransport::new();
let mut client = Client::new(transport);
client.initialize(ClientCapabilities::default()).await?;

// List all resource templates
let templates = client.list_resource_templates(None).await?;
for template in templates.resource_templates {
    println!("Template: {} ({})", template.name, template.uri_template);
    if let Some(description) = template.description {
        println!("  Description: {}", description);
    }
}
§Errors

Returns an error if:

  • The client is not initialized
  • The server doesn’t support resource templates
  • Network or protocol errors occur
Source

pub async fn list_all_tools(&self) -> Result<Vec<ToolInfo>>

List all tools across all pages, auto-paginating on next_cursor.

Loops calling Self::list_tools, terminating when the server returns next_cursor: None. Safety cap: if the loop runs more than self.options.max_iterations iterations (default 100), returns Error::Validation instead of continuing or silently truncating.

Empty-string cursors (Some("")) do NOT terminate the loop — only None does. This matches the MCP spec, which treats the cursor as an opaque server token and does not ascribe meaning to the empty string.

§Memory

This helper accumulates all pages in memory before returning. For very large servers, prefer the paginated single-page Self::list_tools and stream the output yourself — this helper is a convenience API and will amplify memory usage proportional to the total tool count.

§Errors
  • Any error surfaced by Self::list_tools propagates unchanged.
  • Cap exceeded → Error::Validation("list_all_tools exceeded max_iterations cap of N pages").
§Examples
let tools = client.list_all_tools().await?;
println!("discovered {} tools", tools.len());
Source

pub async fn list_all_prompts(&self) -> Result<Vec<PromptInfo>>

List all prompts across all pages, auto-paginating on next_cursor.

Semantics identical to Self::list_all_tools: bounded by self.options.max_iterations, terminates only on next_cursor: None, returns Error::Validation on cap exceeded.

§Memory

Accumulates all pages in memory; prefer Self::list_prompts for very large servers.

§Errors
  • Any error surfaced by Self::list_prompts propagates unchanged.
  • Cap exceeded → Error::Validation("list_all_prompts exceeded max_iterations cap of N pages").
§Examples
let prompts = client.list_all_prompts().await?;
println!("discovered {} prompts", prompts.len());
Source

pub async fn list_all_resources(&self) -> Result<Vec<ResourceInfo>>

List all resources across all pages, auto-paginating on next_cursor.

Semantics identical to Self::list_all_tools: bounded by self.options.max_iterations, terminates only on next_cursor: None, returns Error::Validation on cap exceeded.

§Memory

Accumulates all pages in memory; prefer Self::list_resources for very large servers.

§Errors
  • Any error surfaced by Self::list_resources propagates unchanged.
  • Cap exceeded → Error::Validation("list_all_resources exceeded max_iterations cap of N pages").
§Examples
let resources = client.list_all_resources().await?;
println!("discovered {} resources", resources.len());
Source

pub async fn list_all_resource_templates(&self) -> Result<Vec<ResourceTemplate>>

List all resource templates across all pages, auto-paginating on next_cursor.

Uses the distinct resources/templates/list capability path (all other list_all_* helpers hit their own methods). Semantics otherwise identical to Self::list_all_tools: bounded by self.options.max_iterations, terminates only on next_cursor: None, returns Error::Validation on cap exceeded.

§Memory

Accumulates all pages in memory; prefer Self::list_resource_templates for very large servers.

§Errors
  • Any error surfaced by Self::list_resource_templates propagates unchanged.
  • Cap exceeded → Error::Validation("list_all_resource_templates exceeded max_iterations cap of N pages").
§Examples
let templates = client.list_all_resource_templates().await?;
println!("discovered {} templates", templates.len());
Source

pub async fn read_resource(&self, uri: String) -> Result<ReadResourceResult>

Read a resource.

Retrieves the content of a specific resource from the server by its URI. Resources can contain text, binary data, or structured content.

§Arguments
  • uri - The URI of the resource to read
§Examples
use pmcp::{Client, StdioTransport, ClientCapabilities};

let transport = StdioTransport::new();
let mut client = Client::new(transport);
client.initialize(ClientCapabilities::default()).await?;

// Read a text resource
let resource = client.read_resource("file://readme.txt".to_string()).await?;
for content in resource.contents {
    match content {
        pmcp::Content::Text { text } => {
            println!("Text content: {}", text);
        }
        pmcp::Content::Resource { uri, .. } => {
            println!("Resource reference: {}", uri);
        }
        _ => println!("Other content type"),
    }
}
§Errors

Returns an error if:

  • The client is not initialized
  • The server doesn’t support resources
  • The resource URI doesn’t exist
  • Access to the resource is denied
  • Network or protocol errors occur
§v2 (2026-07-28) behavior

Auto-orchestrates MRTR exactly as Self::call_tool documents. This method is where the missing return type BIT the hardest: ReadResourceResult.contents has no serde default, so an input_required result cannot be deserialized into it at all and would surface as an opaque parse error. It now surfaces as an Error::is_input_required_unfulfilled carrying the full result, or — via Self::read_resource_mrtr — as a value. v1 is byte-identical to every prior release.

Source

pub async fn subscribe_resource(&self, uri: String) -> Result<()>

Subscribe to resource updates.

Subscribes to receive notifications when a resource changes. The server will send notifications when the subscribed resource is modified.

§Arguments
  • uri - The URI of the resource to subscribe to
§Examples
use pmcp::{Client, StdioTransport, ClientCapabilities};

let transport = StdioTransport::new();
let mut client = Client::new(transport);
client.initialize(ClientCapabilities::default()).await?;

// Subscribe to a configuration file
client.subscribe_resource("file://config/settings.json".to_string()).await?;

// Now the client will receive notifications when settings.json changes
// Handle notifications in your event loop
§v2 behavior (2026-07-28)

resources/subscribe was REMOVED from the 2026-07-28 schema and replaced by the subscriptions/listen stream. On a connection that opted into that version this method sends NOTHING and returns Error::retired_on_v2 immediately — a v2 server answers the retired RPC with 404 + -32601, so the round trip can only fail. Use Client::subscriptions_listen with SubscriptionFilter::resource_subscriptions instead. The v1 path below is unchanged.

§Errors

Returns an error if:

  • The connection speaks 2026-07-28 (see v2 behavior above)
  • The client is not initialized
  • The server doesn’t support resource subscriptions
  • The resource URI doesn’t exist
  • Network or protocol errors occur
Source

pub async fn unsubscribe_resource(&self, uri: String) -> Result<()>

Unsubscribe from resource updates.

Unsubscribes from notifications for a previously subscribed resource. After unsubscribing, the client will no longer receive change notifications.

§Arguments
  • uri - The URI of the resource to unsubscribe from
§Examples
use pmcp::{Client, StdioTransport, ClientCapabilities};

let transport = StdioTransport::new();
let mut client = Client::new(transport);
client.initialize(ClientCapabilities::default()).await?;

// Subscribe to a resource
client.subscribe_resource("file://config/settings.json".to_string()).await?;

// Later, unsubscribe when no longer needed
client.unsubscribe_resource("file://config/settings.json".to_string()).await?;
§v2 behavior (2026-07-28)

resources/unsubscribe was REMOVED from the 2026-07-28 schema along with resources/subscribe. On a connection that opted into that version this method sends NOTHING and returns Error::retired_on_v2 immediately. Unsubscribing on v2 means DROPPING the SubscriptionStream returned by Client::subscriptions_listen, which closes the connection and releases the server’s registry slot. The v1 path below is unchanged.

§Errors

Returns an error if:

  • The connection speaks 2026-07-28 (see v2 behavior above)
  • The client is not initialized
  • The server doesn’t support resource subscriptions
  • The resource URI was not previously subscribed to
  • Network or protocol errors occur
Source

pub async fn complete(&self, params: CompleteRequest) -> Result<CompleteResult>

Request completion from the server.

Requests auto-completion suggestions from the server for a given context. This is useful for implementing IDE-like features with contextual suggestions.

§Arguments
  • params - The completion request parameters
§Examples
use pmcp::{Client, StdioTransport, ClientCapabilities, CompleteRequest};

let transport = StdioTransport::new();
let mut client = Client::new(transport);
client.initialize(ClientCapabilities::default()).await?;

// Request completion for partial text
let completion_request = CompleteRequest {
    r#ref: pmcp::CompletionReference::Resource {
        uri: "file://code.rs".to_string(),
    },
    argument: pmcp::CompletionArgument {
        name: "function_name".to_string(),
        value: "calc_".to_string(),
    },
};

let completions = client.complete(completion_request).await?;
for completion in completions.completion.values {
    println!("Suggestion: {}", completion);
}
§Errors

Returns an error if:

  • The client is not initialized
  • The server doesn’t support completions
  • The completion context is invalid
  • Network or protocol errors occur
Source

pub async fn create_message( &self, params: CreateMessageParams, ) -> Result<CreateMessageResult>

Create a message using sampling (for LLM providers).

Requests the server to generate a message using its language model capabilities. This is typically used by servers that provide LLM functionality.

§The “LLM-server pattern” (INVERSE of spec host sampling)

This method is the LLM-server pattern: the client asks a server whose pmcp::SamplingHandler runs the LLM. It is the inverse of MCP spec host sampling, where a server requests sampling and the client answers via a pmcp::client::host::HostSamplingHandler. Both directions are supported and neither is deprecated — pick the one that matches who owns the model. This path is unchanged by the client host surface.

§Examples
use pmcp::{Client, StdioTransport, ClientCapabilities, CreateMessageParams, SamplingMessage};

let mut capabilities = ClientCapabilities::default();
capabilities.sampling = Some(Default::default());

let transport = StdioTransport::new();
let mut client = Client::new(transport);
client.initialize(capabilities).await?;

// Create a message with the LLM
let msg = SamplingMessage::new(
    pmcp::types::Role::User,
    pmcp::types::SamplingMessageContent::Text {
        text: "Explain how to implement a binary search tree".to_string(),
        meta: None,
    },
);
let prefs = pmcp::types::ModelPreferences::new()
    .with_hints(vec![pmcp::types::ModelHint::new("gpt-4")])
    .with_cost_priority(0.5)
    .with_speed_priority(0.3)
    .with_intelligence_priority(0.2);
let mut request = CreateMessageParams::new(vec![msg])
    .with_model_preferences(prefs)
    .with_system_prompt("You are a helpful programming assistant")
    .with_temperature(0.7)
    .with_max_tokens(1000);
request.include_context = pmcp::types::IncludeContext::ThisServer;

let result = client.create_message(request).await?;
println!("Model: {}", result.model);
println!("Response: {:?}", result.content);
§Errors

Returns an error if:

  • The client is not initialized
  • The server doesn’t support sampling
  • The request parameters are invalid
  • Network or protocol errors occur
Source

pub async fn send_roots_list_changed(&self) -> Result<()>

Send roots list changed notification.

Notifies the server that the client’s root list has changed. This is typically sent when the workspace or project roots are modified.

§Examples
use pmcp::{ClientBuilder, StdioTransport, ClientCapabilities};
use pmcp::types::roots::{ListRootsResult, Root};

// Roots advertisement is registry-derived (HOST-05): the client must
// register a roots provider for the `roots` capability to reach the
// wire. Build via `ClientBuilder` and register one with `on_roots`.
let transport = StdioTransport::new();
let mut client = ClientBuilder::new(transport)
    .on_roots(|| async {
        Ok(ListRootsResult {
            roots: vec![Root {
                uri: "file:///workspace".to_string(),
                name: Some("workspace".to_string()),
            }],
        })
    })
    .build();

// With a provider registered, a caller-set `list_changed` is preserved,
// so the client advertises that it emits roots-list-changed notices.
let mut capabilities = ClientCapabilities::default();
capabilities.roots = Some(pmcp::RootsCapabilities { list_changed: true });
client.initialize(capabilities).await?;

// Notify server when project roots change
client.send_roots_list_changed().await?;
§Errors

Returns an error if:

  • The client is not initialized
  • The client doesn’t support roots list changed notifications
  • Network or protocol errors occur
Source

pub fn authenticate(&self, auth_info: &AuthInfo) -> Result<()>

Authenticate with the server.

Performs authentication using the provided authentication information. This should be called after initialization if the server requires authentication.

§Examples
use pmcp::{Client, StdioTransport, AuthInfo, AuthScheme};

let transport = StdioTransport::new();
let mut client = Client::new(transport);

// Initialize first
client.initialize(pmcp::ClientCapabilities::default()).await?;

// Authenticate with bearer token
let auth = AuthInfo {
    scheme: AuthScheme::Bearer,
    token: Some("your-api-token".to_string()),
    oauth: None,
    params: Default::default(),
};

client.authenticate(&auth)?;
§Errors

Returns an error if:

  • The client is not initialized
  • Authentication fails
  • The server doesn’t support authentication
Source

pub async fn cancel_request(&self, request_id: &RequestId) -> Result<()>

Cancel a request.

Sends a cancellation notification for an active request. This allows graceful termination of long-running operations.

§Arguments
  • request_id - The ID of the request to cancel
§Examples
use pmcp::{Client, StdioTransport, ClientCapabilities, RequestId};
use serde_json::json;

let transport = StdioTransport::new();
let mut client = Client::new(transport);
client.initialize(ClientCapabilities::default()).await?;

// Start a long-running operation
let request_id = RequestId::String("long-operation-123".to_string());

// Later, cancel the request if needed
client.cancel_request(&request_id).await?;
§Errors

Returns an error if:

  • Network or protocol errors occur while sending the cancellation
Source

pub async fn send_progress(&self, progress: ProgressNotification) -> Result<()>

Send a progress notification.

Sends a progress update for a long-running operation. This allows the server or client to track operation progress.

§Arguments
  • progress - The progress notification to send
§Examples
use pmcp::{Client, StdioTransport, ClientCapabilities, ProgressNotification, RequestId};

let transport = StdioTransport::new();
let mut client = Client::new(transport);
client.initialize(ClientCapabilities::default()).await?;

// Send progress update for a file processing operation
let progress = ProgressNotification::new(
    pmcp::ProgressToken::String("file-processing".to_string()),
    75.0,
    Some("Processing files...".to_string()),
);

client.send_progress(progress).await?;
§Errors

Returns an error if:

  • Network or protocol errors occur while sending the notification
Source

pub async fn call_tool_mrtr( &self, name: String, arguments: Value, ) -> Result<MrtrOutcome<CallToolResult>>

Call a tool, auto-orchestrating MRTR, and observe an unfulfilled input_required result instead of losing it (Phase 113, CLNT-02).

The additive sibling of Self::call_tool. Use it whenever a MrtrOutcome::InputRequired is a normal outcome for your application rather than an error — for example when your client wants to surface the server’s inputRequests in its own UI instead of registering a ClientBuilder::on_elicitation handler.

On a v1 connection there is no MRTR, so this simply delegates to Self::call_tool and always returns MrtrOutcome::Complete.

§Errors

As Self::call_tool, plus Error::mrtr_round_limit_exceeded when the server keeps asking for input past ClientBuilder::mrtr_round_limit.

Source

pub async fn get_prompt_mrtr( &self, name: String, arguments: HashMap<String, String>, ) -> Result<MrtrOutcome<GetPromptResult>>

Get a prompt, auto-orchestrating MRTR. See Self::call_tool_mrtr.

§Errors

As Self::get_prompt, plus Error::mrtr_round_limit_exceeded.

Source

pub async fn read_resource_mrtr( &self, uri: String, ) -> Result<MrtrOutcome<ReadResourceResult>>

Read a resource, auto-orchestrating MRTR. See Self::call_tool_mrtr.

This one matters even more than the others: ReadResourceResult.contents has no serde default, so an input_required result cannot be deserialized into it at all — without this method (or Error::input_required_unfulfilled) the outcome would surface as an opaque parse error.

§Errors

As Self::read_resource, plus Error::mrtr_round_limit_exceeded.

Source§

impl<T> Client<T>

Source

pub async fn subscriptions_listen( &self, notifications: SubscriptionFilter, ) -> Result<SubscriptionStream>

Available on crate feature streamable-http and non-WebAssembly only.

Open a v2 subscriptions/listen stream and receive change notifications (HTTP-04).

The 2026-07-28 schema REMOVED resources/subscribe and resources/unsubscribe and replaced both with this single long-lived stream. The returned SubscriptionStream has already consumed the server’s mandatory acknowledgement — read the AGREED filter from acknowledged() before polling — and then yields one item per delivered notification.

Dropping the returned stream closes the underlying HTTP response, which is what releases the server’s registry slot; there is no close() to forget.

§Every call mints a FRESH subscription id

The subscription id IS the JSON-RPC request id of this call, and this method mints a fresh Uuid::new_v4() for it every time. It is never derived from the transport, from a counter, or from a previous stream.

That is a CONTRACT, not an implementation detail, and it is what makes a pmcp client structurally immune to the reconnect collision: the server refuses a second LIVE registration under a (principal, subscriptionId) pair it already holds, and it CANNOT tell an ungracefully disconnected peer from a live one (the receiver and the registry guard live in one stream-state tuple, so the entry survives until Hyper drops the response body — at which moment RAII reclaims it anyway). A client that reused its id when reconnecting would therefore be refused for the remainder of the server’s keep-alive window. Because every call here mints a fresh id, a reconnect after ANY disconnect — graceful or not — can never collide with the incumbent the server may still consider live.

The guard against a future refactor making ids sticky is the live tripwire successive_listen_calls_mint_distinct_subscription_ids in tests/v2_subscriptions_client.rs, which opens two streams from ONE client and asserts their acknowledged ids DIFFER.

A third-party client that does reuse an id is refused with the RETRYABLE RATE_LIMITED (-32005, delivered at HTTP 200), so backing off and retrying is the correct response — but minting a fresh id, as this method does, is strictly better.

Polling over the Tasks mechanism stays pmcp’s recommended mechanism for enterprise remote deployments. This stream is the spec-conformant OPT-IN: its server side is documented single-instance / sticky-routed only, because the server’s subscription registry is instance-local. Behind a non-sticky load balancer a subscriber silently under-receives.

§Examples
use futures::StreamExt;
use pmcp::shared::streamable_http::StreamableHttpTransportConfigBuilder;
use pmcp::shared::StreamableHttpTransport;
use pmcp::types::protocol::{ProtocolVersion, PROTOCOL_VERSION_2026_07_28};
use pmcp::types::subscriptions::SubscriptionFilter;
use pmcp::ClientBuilder;

let url = url::Url::parse("https://example.invalid/mcp").unwrap();
let transport =
    StreamableHttpTransport::new(StreamableHttpTransportConfigBuilder::new(url).build());
let client = ClientBuilder::new(transport)
    .with_protocol_version(ProtocolVersion(PROTOCOL_VERSION_2026_07_28.to_string()))?
    .build();

let filter = SubscriptionFilter {
    tools_list_changed: Some(true),
    ..SubscriptionFilter::default()
};
let mut stream = client.subscriptions_listen(filter).await?;
println!("agreed: {:?}", stream.acknowledged().notifications);

while let Some(notification) = stream.next().await {
    println!("{:?}", notification?);
}
§Errors

Returns an error when:

  • the connection did not opt into 2026-07-28 — NO request is sent, and the message names ClientBuilder::with_protocol_version;
  • the server rejected the request, in which case its own JSON-RPC error is returned UNCHANGED (a server advertising no subscription-delivered capability answers -32601, which is how “this server does not do subscriptions” is distinguished from a transport fault);
  • the first frame on the stream is not the mandatory acknowledgement, or is tagged with a different subscriptionId.

Trait Implementations§

Source§

impl<T: Transport> Clone for Client<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: 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> !RefUnwindSafe for Client<T>

§

impl<T> !UnwindSafe for Client<T>

§

impl<T> Freeze for Client<T>

§

impl<T> Send for Client<T>

§

impl<T> Sync for Client<T>

§

impl<T> Unpin for Client<T>

§

impl<T> UnsafeUnpin 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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
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> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. 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<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