use crate::mcp_client::client_runtime::ClientInternalHandler;
use crate::mcp_traits::McpClient;
use crate::schema::schema_utils::{CustomNotification, CustomRequest};
use crate::schema::{
CancelTaskParams, CancelTaskRequest, CancelTaskResult, CancelledNotificationParams,
CreateMessageRequest, CreateMessageRequestParams, CreateMessageResult, ElicitCompleteParams,
ElicitRequest, ElicitRequestParams, ElicitResult, GenericResult, GetTaskParams,
GetTaskPayloadParams, GetTaskPayloadRequest, GetTaskRequest, GetTaskResult, ListRootsRequest,
ListRootsResult, ListTasksRequest, ListTasksResult, LoggingMessageNotificationParams,
NotificationParams, PaginatedRequestParams, ProgressNotificationParams, RequestParams,
ResourceUpdatedNotificationParams, Result, RpcError, TaskStatusNotificationParams,
};
use crate::task_store::ClientTaskCreator;
use crate::{McpClientHandler, ToMcpClientHandler};
use async_trait::async_trait;
use rust_mcp_schema::CreateTaskResult;
#[allow(unused)]
#[async_trait]
pub trait ClientHandler: Send + Sync + 'static {
async fn handle_ping_request(
&self,
params: Option<RequestParams>,
runtime: &dyn McpClient,
) -> std::result::Result<Result, RpcError> {
Ok(Result::default())
}
async fn handle_create_message_request(
&self,
params: CreateMessageRequestParams,
runtime: &dyn McpClient,
) -> std::result::Result<CreateMessageResult, RpcError> {
Err(RpcError::method_not_found().with_message(format!(
"No handler is implemented for '{}'.",
CreateMessageRequest::method_value()
)))
}
async fn handle_task_augmented_create_message(
&self,
params: CreateMessageRequestParams,
runtime: &dyn McpClient,
) -> std::result::Result<CreateTaskResult, RpcError> {
if !runtime.capabilities().can_accept_sampling_task() {
return Err(RpcError::invalid_request()
.with_message("Task-augmented sampling is not supported.".to_string()));
}
Err(RpcError::method_not_found().with_message(format!(
"No handler is implemented for task-augmented '{}'.",
CreateMessageRequest::method_value()
)))
}
async fn handle_list_roots_request(
&self,
params: Option<RequestParams>,
runtime: &dyn McpClient,
) -> std::result::Result<ListRootsResult, RpcError> {
Err(RpcError::method_not_found().with_message(format!(
"No handler is implemented for '{}'.",
ListRootsRequest::method_value(),
)))
}
async fn handle_elicit_request(
&self,
params: ElicitRequestParams,
runtime: &dyn McpClient,
) -> std::result::Result<ElicitResult, RpcError> {
Err(RpcError::method_not_found().with_message(format!(
"No handler is implemented for '{}'.",
ElicitRequest::method_value()
)))
}
async fn handle_task_augmented_elicit_request(
&self,
task_creator: ClientTaskCreator,
params: ElicitRequestParams,
runtime: &dyn McpClient,
) -> std::result::Result<CreateTaskResult, RpcError> {
Err(RpcError::method_not_found().with_message(format!(
"No handler is implemented for '{}'.",
ElicitRequest::method_value()
)))
}
async fn handle_get_task_request(
&self,
params: GetTaskParams,
runtime: &dyn McpClient,
) -> std::result::Result<GetTaskResult, RpcError> {
Err(RpcError::method_not_found().with_message(format!(
"No handler is implemented for '{}'.",
GetTaskRequest::method_value()
)))
}
async fn handle_get_task_payload_request(
&self,
params: GetTaskPayloadParams,
runtime: &dyn McpClient,
) -> std::result::Result<GenericResult, RpcError> {
Err(RpcError::method_not_found().with_message(format!(
"No handler is implemented for '{}'.",
GetTaskPayloadRequest::method_value()
)))
}
async fn handle_cancel_task_request(
&self,
params: CancelTaskParams,
runtime: &dyn McpClient,
) -> std::result::Result<CancelTaskResult, RpcError> {
Err(RpcError::method_not_found().with_message(format!(
"No handler is implemented for '{}'.",
CancelTaskRequest::method_value()
)))
}
async fn handle_list_tasks_request(
&self,
params: Option<PaginatedRequestParams>,
runtime: &dyn McpClient,
) -> std::result::Result<ListTasksResult, RpcError> {
Err(RpcError::method_not_found().with_message(format!(
"No handler is implemented for '{}'.",
ListTasksRequest::method_value()
)))
}
async fn handle_custom_request(
&self,
request: CustomRequest,
runtime: &dyn McpClient,
) -> std::result::Result<ListRootsResult, RpcError> {
Err(RpcError::method_not_found().with_message(format!(
"No handler for custom request : \"{}\"",
request.method
)))
}
async fn handle_cancelled_notification(
&self,
params: CancelledNotificationParams,
runtime: &dyn McpClient,
) -> std::result::Result<(), RpcError> {
Ok(())
}
async fn handle_progress_notification(
&self,
params: ProgressNotificationParams,
runtime: &dyn McpClient,
) -> std::result::Result<(), RpcError> {
Ok(())
}
async fn handle_resource_list_changed_notification(
&self,
params: Option<NotificationParams>,
runtime: &dyn McpClient,
) -> std::result::Result<(), RpcError> {
Ok(())
}
async fn handle_resource_updated_notification(
&self,
params: ResourceUpdatedNotificationParams,
runtime: &dyn McpClient,
) -> std::result::Result<(), RpcError> {
Ok(())
}
async fn handle_prompt_list_changed_notification(
&self,
params: Option<NotificationParams>,
runtime: &dyn McpClient,
) -> std::result::Result<(), RpcError> {
Ok(())
}
async fn handle_tool_list_changed_notification(
&self,
params: Option<NotificationParams>,
runtime: &dyn McpClient,
) -> std::result::Result<(), RpcError> {
Ok(())
}
async fn handle_logging_message_notification(
&self,
params: LoggingMessageNotificationParams,
runtime: &dyn McpClient,
) -> std::result::Result<(), RpcError> {
Ok(())
}
async fn handle_task_status_notification(
&self,
params: TaskStatusNotificationParams,
runtime: &dyn McpClient,
) -> std::result::Result<(), RpcError> {
Ok(())
}
async fn handle_elicitation_complete_notification(
&self,
params: ElicitCompleteParams,
runtime: &dyn McpClient,
) -> std::result::Result<(), RpcError> {
Ok(())
}
async fn handle_custom_notification(
&self,
notification: CustomNotification,
runtime: &dyn McpClient,
) -> std::result::Result<(), RpcError> {
Ok(())
}
async fn handle_error(
&self,
error: &RpcError,
runtime: &dyn McpClient,
) -> std::result::Result<(), RpcError> {
Ok(())
}
async fn handle_process_error(
&self,
error_message: String,
runtime: &dyn McpClient,
) -> std::result::Result<(), RpcError> {
if !runtime.is_shut_down().await {
tracing::error!("Process error: {error_message}");
}
Ok(())
}
}
impl<T: ClientHandler + 'static> ToMcpClientHandler for T {
fn to_mcp_client_handler(self) -> Box<dyn McpClientHandler + 'static> {
Box::new(ClientInternalHandler::new(Box::new(self)))
}
}