use crate::builder::{NotRegistered, Registered};
use crate::context::Context;
use crate::handler::{CompletionHandler, PromptHandler, ResourceHandler, TaskHandler, ToolHandler};
use mcpkit_core::error::McpError;
use mcpkit_core::types::{
CancelTaskResult, CompleteRequest, CompleteResult, GetPromptResult, GetTaskResult,
ListTasksResult, Object, Prompt, Resource, ResourceContents, ResourceTemplate, TaskId, Tool,
ToolOutput,
};
use serde_json::Value;
use std::future::Future;
use std::pin::Pin;
type BoxFut<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
pub trait DynToolHandler: Send + Sync {
fn list_tools<'a>(&'a self, ctx: &'a Context<'_>) -> BoxFut<'a, Result<Vec<Tool>, McpError>>;
fn call_tool<'a>(
&'a self,
name: &'a str,
args: Object,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<ToolOutput, McpError>>;
}
impl<T: ToolHandler> DynToolHandler for T {
fn list_tools<'a>(&'a self, ctx: &'a Context<'_>) -> BoxFut<'a, Result<Vec<Tool>, McpError>> {
Box::pin(ToolHandler::list_tools(self, ctx))
}
fn call_tool<'a>(
&'a self,
name: &'a str,
args: Object,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<ToolOutput, McpError>> {
Box::pin(ToolHandler::call_tool(self, name, args, ctx))
}
}
pub trait DynResourceHandler: Send + Sync {
fn list_resources<'a>(
&'a self,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<Vec<Resource>, McpError>>;
fn list_resource_templates<'a>(
&'a self,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<Vec<ResourceTemplate>, McpError>>;
fn read_resource<'a>(
&'a self,
uri: &'a str,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<Vec<ResourceContents>, McpError>>;
fn subscribe<'a>(
&'a self,
uri: &'a str,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<bool, McpError>>;
fn unsubscribe<'a>(
&'a self,
uri: &'a str,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<bool, McpError>>;
}
impl<R: ResourceHandler> DynResourceHandler for R {
fn list_resources<'a>(
&'a self,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<Vec<Resource>, McpError>> {
Box::pin(ResourceHandler::list_resources(self, ctx))
}
fn list_resource_templates<'a>(
&'a self,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<Vec<ResourceTemplate>, McpError>> {
Box::pin(ResourceHandler::list_resource_templates(self, ctx))
}
fn read_resource<'a>(
&'a self,
uri: &'a str,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<Vec<ResourceContents>, McpError>> {
Box::pin(ResourceHandler::read_resource(self, uri, ctx))
}
fn subscribe<'a>(
&'a self,
uri: &'a str,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<bool, McpError>> {
Box::pin(ResourceHandler::subscribe(self, uri, ctx))
}
fn unsubscribe<'a>(
&'a self,
uri: &'a str,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<bool, McpError>> {
Box::pin(ResourceHandler::unsubscribe(self, uri, ctx))
}
}
pub trait DynPromptHandler: Send + Sync {
fn list_prompts<'a>(
&'a self,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<Vec<Prompt>, McpError>>;
fn get_prompt<'a>(
&'a self,
name: &'a str,
args: Option<serde_json::Map<String, Value>>,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<GetPromptResult, McpError>>;
}
impl<P: PromptHandler> DynPromptHandler for P {
fn list_prompts<'a>(
&'a self,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<Vec<Prompt>, McpError>> {
Box::pin(PromptHandler::list_prompts(self, ctx))
}
fn get_prompt<'a>(
&'a self,
name: &'a str,
args: Option<serde_json::Map<String, Value>>,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<GetPromptResult, McpError>> {
Box::pin(PromptHandler::get_prompt(self, name, args, ctx))
}
}
pub trait DynTaskHandler: Send + Sync {
fn list_tasks<'a>(
&'a self,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<ListTasksResult, McpError>>;
fn get_task<'a>(
&'a self,
id: &'a TaskId,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<Option<GetTaskResult>, McpError>>;
fn cancel_task<'a>(
&'a self,
id: &'a TaskId,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<Option<CancelTaskResult>, McpError>>;
}
impl<K: TaskHandler> DynTaskHandler for K {
fn list_tasks<'a>(
&'a self,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<ListTasksResult, McpError>> {
Box::pin(TaskHandler::list_tasks(self, ctx))
}
fn get_task<'a>(
&'a self,
id: &'a TaskId,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<Option<GetTaskResult>, McpError>> {
Box::pin(TaskHandler::get_task(self, id, ctx))
}
fn cancel_task<'a>(
&'a self,
id: &'a TaskId,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<Option<CancelTaskResult>, McpError>> {
Box::pin(TaskHandler::cancel_task(self, id, ctx))
}
}
pub trait DynCompletionHandler: Send + Sync {
fn complete<'a>(
&'a self,
request: &'a CompleteRequest,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<CompleteResult, McpError>>;
}
impl<C: CompletionHandler> DynCompletionHandler for C {
fn complete<'a>(
&'a self,
request: &'a CompleteRequest,
ctx: &'a Context<'_>,
) -> BoxFut<'a, Result<CompleteResult, McpError>> {
Box::pin(CompletionHandler::complete(self, request, ctx))
}
}
pub trait ToolSlot: Send + Sync {
fn as_tool_handler(&self) -> Option<&dyn DynToolHandler>;
}
impl ToolSlot for NotRegistered {
fn as_tool_handler(&self) -> Option<&dyn DynToolHandler> {
None
}
}
impl<T: ToolHandler> ToolSlot for Registered<T> {
fn as_tool_handler(&self) -> Option<&dyn DynToolHandler> {
Some(&self.0)
}
}
pub trait ResourceSlot: Send + Sync {
fn as_resource_handler(&self) -> Option<&dyn DynResourceHandler>;
}
impl ResourceSlot for NotRegistered {
fn as_resource_handler(&self) -> Option<&dyn DynResourceHandler> {
None
}
}
impl<R: ResourceHandler> ResourceSlot for Registered<R> {
fn as_resource_handler(&self) -> Option<&dyn DynResourceHandler> {
Some(&self.0)
}
}
pub trait PromptSlot: Send + Sync {
fn as_prompt_handler(&self) -> Option<&dyn DynPromptHandler>;
}
impl PromptSlot for NotRegistered {
fn as_prompt_handler(&self) -> Option<&dyn DynPromptHandler> {
None
}
}
impl<P: PromptHandler> PromptSlot for Registered<P> {
fn as_prompt_handler(&self) -> Option<&dyn DynPromptHandler> {
Some(&self.0)
}
}
pub trait TaskSlot: Send + Sync {
fn as_task_handler(&self) -> Option<&dyn DynTaskHandler>;
}
impl TaskSlot for NotRegistered {
fn as_task_handler(&self) -> Option<&dyn DynTaskHandler> {
None
}
}
impl<K: TaskHandler> TaskSlot for Registered<K> {
fn as_task_handler(&self) -> Option<&dyn DynTaskHandler> {
Some(&self.0)
}
}