pub trait PluginProvider: Send + Sync {
// Required methods
fn tools(&self) -> Vec<Tool>;
fn call_tool<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
arguments: Value,
context: PluginRequestContext,
) -> Pin<Box<dyn Future<Output = PluginResult<ToolResult>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
// Provided methods
fn resources(&self) -> Vec<Resource> { ... }
fn resource_templates(&self) -> Vec<ResourceTemplate> { ... }
fn read_resource<'life0, 'life1, 'async_trait>(
&'life0 self,
uri: &'life1 str,
context: PluginRequestContext,
) -> Pin<Box<dyn Future<Output = PluginResult<ResourceResult>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn prompts(&self) -> Vec<Prompt> { ... }
fn get_prompt<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
arguments: Option<Value>,
context: PluginRequestContext,
) -> Pin<Box<dyn Future<Output = PluginResult<PromptResult>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn complete<'life0, 'async_trait>(
&'life0 self,
request: CompletionRequest,
context: PluginRequestContext,
) -> Pin<Box<dyn Future<Output = PluginResult<Completion>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn start<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = PluginResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn shutdown<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
}Expand description
Object-safe MCP tool provider implemented by a plugin.
New methods are added with defaults, so a plugin never has to change to keep compiling against a later version of this contract.
Required Methods§
Sourcefn call_tool<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
arguments: Value,
context: PluginRequestContext,
) -> Pin<Box<dyn Future<Output = PluginResult<ToolResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn call_tool<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
arguments: Value,
context: PluginRequestContext,
) -> Pin<Box<dyn Future<Output = PluginResult<ToolResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Call a local, unprefixed tool.
The host applies a wall-clock budget to this call and isolates panics,
so a hung or panicking plugin degrades to one failed tool call rather
than a stalled or downed server. Long work belongs in a task the plugin
owns and tears down in Self::shutdown.
Provided Methods§
Sourcefn resources(&self) -> Vec<Resource>
fn resources(&self) -> Vec<Resource>
Return local, unprefixed resource descriptors.
Resources are the primitive a client attaches as context on the user’s initiative, which is different from a tool the model decides to call. State a plugin maintains — index statistics, a rendered summary — is usually better offered here than as a tool nothing thinks to invoke.
Give each uri a plugin-local path; the host publishes it under this
plugin’s scheme. Default: none.
List only what is worth enumerating. A URI space too large or too
volatile to enumerate belongs in Self::resource_templates instead.
Sourcefn resource_templates(&self) -> Vec<ResourceTemplate>
fn resource_templates(&self) -> Vec<ResourceTemplate>
Return local, unprefixed URI templates for resources this plugin serves but does not enumerate.
This is how a plugin exposes a URI space that is large, open-ended, or
changes as the vault does — note/{path} rather than one entry per
note. TurboVault never sends list_changed notifications, so a resource
that comes and goes has to be reachable through a template; an
enumerated list a client cached at startup would go stale silently.
The host routes this plugin’s entire scheme, so a read of any URI under
it reaches Self::read_resource whether or not it was listed.
Default: none.
Sourcefn read_resource<'life0, 'life1, 'async_trait>(
&'life0 self,
uri: &'life1 str,
context: PluginRequestContext,
) -> Pin<Box<dyn Future<Output = PluginResult<ResourceResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn read_resource<'life0, 'life1, 'async_trait>(
&'life0 self,
uri: &'life1 str,
context: PluginRequestContext,
) -> Pin<Box<dyn Future<Output = PluginResult<ResourceResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Read one local, unprefixed resource path.
Called for any URI in this plugin’s scheme, including ones matching a template rather than an enumerated entry, so validate what you receive.
The host rewrites the URI on every returned content into this plugin’s namespace, so what a client reads back always matches what it asked for and a plugin cannot publish content under a URI it does not own.
Bounded and panic-isolated exactly like Self::call_tool. Default:
not found.
Sourcefn prompts(&self) -> Vec<Prompt>
fn prompts(&self) -> Vec<Prompt>
Return local, unprefixed prompt descriptors.
Prompts are user-invoked, so this is how a plugin offers a workflow a person starts deliberately rather than one the model reaches for. Names are namespaced like tools. Default: none.
Sourcefn get_prompt<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
arguments: Option<Value>,
context: PluginRequestContext,
) -> Pin<Box<dyn Future<Output = PluginResult<PromptResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_prompt<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
arguments: Option<Value>,
context: PluginRequestContext,
) -> Pin<Box<dyn Future<Output = PluginResult<PromptResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Render one local, unprefixed prompt.
Bounded and panic-isolated exactly like Self::call_tool. Default:
not found.
Sourcefn complete<'life0, 'async_trait>(
&'life0 self,
request: CompletionRequest,
context: PluginRequestContext,
) -> Pin<Box<dyn Future<Output = PluginResult<Completion>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn complete<'life0, 'async_trait>(
&'life0 self,
request: CompletionRequest,
context: PluginRequestContext,
) -> Pin<Box<dyn Future<Output = PluginResult<Completion>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Suggest values for an argument a user is part-way through typing.
This is what makes a resource template usable rather than merely declared: a client can offer the paths that exist instead of asking a person to guess one. It applies to prompt arguments equally.
Called on every keystroke in some clients, so answer from state the plugin already holds. The host applies the same wall-clock budget as a tool call and truncates the result to the protocol’s limit, so returning everything known is safe.
Default: no suggestions, which is a valid answer for any argument.
Sourcefn start<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = PluginResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn start<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = PluginResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Begin background work.
Called once, on the host’s runtime, after every plugin is mounted and
before the transport starts serving. This is where a worker belongs:
Plugin::build is synchronous and may run outside a runtime, so
spawning there is not sound.
Return promptly. Spawn the loop and keep its handle; the
ShutdownSignal from PluginContext tells it when to stop, and
Self::shutdown is where to await the handle.
A failure here stops the server from starting: a plugin that cannot begin its work would otherwise serve tools backed by state it is not maintaining. Default: nothing.
Sourcefn shutdown<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn shutdown<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Release resources during graceful host shutdown.
Called once, after the host stops accepting requests and after the shutdown signal has fired, so a worker has already been told to stop. Await your task handles here. Default: nothing.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".