Skip to main content

McpToolset

Struct McpToolset 

Source
pub struct McpToolset<S = ()>
where S: Service<RoleClient> + Send + Sync + 'static,
{ /* private fields */ }
Available on crate feature tools only.
Expand description

MCP Toolset - connects to an MCP server and exposes its tools as ADK tools.

This toolset implements the ADK Toolset trait and bridges the gap between MCP servers and ADK agents. It:

  1. Connects to an MCP server via the provided transport
  2. Discovers available tools from the server
  3. Converts MCP tools to ADK-compatible Tool implementations
  4. Proxies tool execution calls to the MCP server

§Example

use adk_tool::McpToolset;
use rmcp::{ServiceExt, transport::TokioChildProcess};
use tokio::process::Command;

// Create MCP client connection to a local server
let client = ().serve(TokioChildProcess::new(
    Command::new("npx")
        .arg("-y")
        .arg("@modelcontextprotocol/server-everything")
)?).await?;

// Create toolset from the client
let toolset = McpToolset::new(client);

// Add to agent
let agent = LlmAgentBuilder::new("assistant")
    .toolset(Arc::new(toolset))
    .build()?;

Implementations§

Source§

impl<S> McpToolset<S>
where S: Service<RoleClient> + Send + Sync + 'static,

Source

pub fn new(client: RunningService<RoleClient, S>) -> McpToolset<S>

Create a new MCP toolset from a running MCP client service.

The client should already be connected and initialized. Use rmcp::ServiceExt::serve() to create the client.

§Example
use rmcp::{ServiceExt, transport::TokioChildProcess};
use tokio::process::Command;

let client = ().serve(TokioChildProcess::new(
    Command::new("my-mcp-server")
)?).await?;

let toolset = McpToolset::new(client);
Source

pub fn with_client_handler( client: RunningService<RoleClient, S>, ) -> McpToolset<S>

Create a McpToolset from a RunningService with a custom ClientHandler.

This is functionally identical to new() but makes the intent explicit when using a custom ClientHandler type.

§Example
use rmcp::ServiceExt;
use adk_tool::McpToolset;

let client = my_custom_handler.serve(transport).await?;
let toolset = McpToolset::with_client_handler(client);
Source

pub fn with_name(self, name: impl Into<String>) -> McpToolset<S>

Set a custom name for this toolset.

Source

pub fn with_task_support(self, config: McpTaskConfig) -> McpToolset<S>

Enable task support for long-running operations.

When enabled, tools marked as is_long_running() will use MCP’s async task lifecycle (SEP-1686) instead of blocking calls.

§Example
let toolset = McpToolset::new(client)
    .with_task_support(McpTaskConfig::enabled()
        .poll_interval(Duration::from_secs(2))
        .timeout(Duration::from_secs(300)));
Source

pub fn with_connection_factory<F>(self, factory: Arc<F>) -> McpToolset<S>
where F: ConnectionFactory<S> + 'static,

Provide a connection factory to enable automatic MCP reconnection.

Source

pub fn with_refresh_config(self, config: RefreshConfig) -> McpToolset<S>

Configure MCP reconnect/retry behavior.

Source

pub fn with_filter<F>(self, filter: F) -> McpToolset<S>
where F: Fn(&str) -> bool + Send + Sync + 'static,

Add a filter to select which tools to expose.

The filter function receives a tool name and returns true if the tool should be included.

§Example
let toolset = McpToolset::new(client)
    .with_filter(|name| {
        matches!(name, "read_file" | "list_directory" | "search_files")
    });
Source

pub fn with_tools(self, tool_names: &[&str]) -> McpToolset<S>

Add a filter that only includes tools with the specified names.

§Example
let toolset = McpToolset::new(client)
    .with_tools(&["read_file", "write_file"]);
Source

pub async fn cancellation_token(&self) -> RunningServiceCancellationToken

Get a cancellation token that can be used to shutdown the MCP server.

Call cancel() on the returned token to cleanly shutdown the MCP server. This should be called before exiting to avoid EPIPE errors.

§Example
let toolset = McpToolset::new(client);
let cancel_token = toolset.cancellation_token().await;

// ... use the toolset ...

// Before exiting:
cancel_token.cancel();
Source

pub async fn list_resources( &self, ) -> Result<Vec<Annotated<RawResource>>, AdkError>

List static resources from the connected MCP server.

Returns the list of resources advertised by the server via the resources/list protocol method. Returns an empty Vec when the server does not support resources (i.e. responds with MethodNotFound).

§Errors

Returns AdkError::Tool on transport or unexpected server errors.

Source

pub async fn list_resource_templates( &self, ) -> Result<Vec<Annotated<RawResourceTemplate>>, AdkError>

List URI template resources from the connected MCP server.

Returns the list of resource templates advertised by the server via the resourceTemplates/list protocol method. Returns an empty Vec when the server does not support resource templates (i.e. responds with MethodNotFound).

§Errors

Returns AdkError::Tool on transport or unexpected server errors.

Source

pub async fn read_resource( &self, uri: &str, ) -> Result<Vec<ResourceContents>, AdkError>

Read a resource by URI from the connected MCP server.

Delegates to the resources/read protocol method. Returns the resource contents on success.

§Errors

Returns AdkError::Tool("resource not found: {uri}") when the URI does not match any resource on the server. Returns a generic AdkError::Tool on transport or other server errors.

Source§

impl McpToolset<AdkClientHandler>

Source

pub async fn with_elicitation_handler<T, E, A>( transport: T, handler: Arc<dyn ElicitationHandler>, ) -> Result<McpToolset<AdkClientHandler>, AdkError>
where T: IntoTransport<RoleClient, E, A> + Send + 'static, E: Error + Send + Sync + 'static,

Create a McpToolset with elicitation support from a transport.

This creates the MCP client using AdkClientHandler, which advertises elicitation capabilities and delegates requests to the provided handler.

§Example
use adk_tool::{McpToolset, ElicitationHandler, AutoDeclineElicitationHandler};
use rmcp::transport::TokioChildProcess;
use tokio::process::Command;
use std::sync::Arc;

let transport = TokioChildProcess::new(Command::new("my-mcp-server"))?;
let handler = Arc::new(AutoDeclineElicitationHandler);
let toolset = McpToolset::with_elicitation_handler(transport, handler).await?;
§ConnectionFactory with Elicitation

To preserve elicitation across reconnections, clone the Arc<dyn ElicitationHandler> into your ConnectionFactory implementation:

use adk_tool::{McpToolset, ElicitationHandler};
use adk_tool::mcp::ConnectionFactory;
use rmcp::{ServiceExt, service::{RoleClient, RunningService}};
use rmcp::transport::TokioChildProcess;
use tokio::process::Command;
use std::sync::Arc;

struct MyReconnectFactory {
    handler: Arc<dyn ElicitationHandler>,
    server_command: String,
}

// The factory creates a fresh AdkClientHandler on each reconnection,
// so the new connection advertises elicitation capabilities.
// The ConnectionFactory trait itself is unchanged.

Trait Implementations§

Source§

impl<S> Toolset for McpToolset<S>
where S: Service<RoleClient> + Send + Sync + 'static,

Source§

fn name(&self) -> &str

Source§

fn tools<'life0, 'async_trait>( &'life0 self, _ctx: Arc<dyn ReadonlyContext>, ) -> Pin<Box<dyn Future<Output = Result<Vec<Arc<dyn Tool>>, AdkError>> + Send + 'async_trait>>
where 'life0: 'async_trait, McpToolset<S>: 'async_trait,

Auto Trait Implementations§

§

impl<S> Freeze for McpToolset<S>

§

impl<S = ()> !RefUnwindSafe for McpToolset<S>

§

impl<S> Send for McpToolset<S>

§

impl<S> Sync for McpToolset<S>

§

impl<S> Unpin for McpToolset<S>

§

impl<S> UnsafeUnpin for McpToolset<S>

§

impl<S = ()> !UnwindSafe for McpToolset<S>

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> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

Source§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
Source§

impl<L> LayerExt<L> for L

Source§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in Layered.
Source§

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

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: 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: 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> Same for T

Source§

type Output = T

Should always be Self
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