use mcpkit_core::capability::{ServerCapabilities, ServerInfo};
use mcpkit_core::error::McpError;
use mcpkit_core::types::{
GetPromptResult, Prompt, Resource, ResourceContents, ResourceTemplate, Task, TaskId, Tool,
ToolOutput,
elicitation::{ElicitRequest, ElicitResult},
sampling::{CreateMessageRequest, CreateMessageResult},
};
use serde_json::Value;
use std::future::Future;
use crate::context::Context;
pub trait ServerHandler: Send + Sync {
fn server_info(&self) -> ServerInfo;
fn capabilities(&self) -> ServerCapabilities {
ServerCapabilities::default()
}
fn instructions(&self) -> Option<String> {
None
}
fn on_initialized(&self, _ctx: &Context<'_>) -> impl Future<Output = ()> + Send {
async {}
}
fn on_shutdown(&self) -> impl Future<Output = ()> + Send {
async {}
}
}
pub trait ToolHandler: Send + Sync {
fn list_tools(
&self,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<Tool>, McpError>> + Send;
fn call_tool(
&self,
name: &str,
args: Value,
ctx: &Context<'_>,
) -> impl Future<Output = Result<ToolOutput, McpError>> + Send;
fn on_tools_changed(&self) -> impl Future<Output = ()> + Send {
async {}
}
}
pub trait ResourceHandler: Send + Sync {
fn list_resources(
&self,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<Resource>, McpError>> + Send;
fn list_resource_templates(
&self,
_ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<ResourceTemplate>, McpError>> + Send {
async { Ok(vec![]) }
}
fn read_resource(
&self,
uri: &str,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<ResourceContents>, McpError>> + Send;
fn subscribe(
&self,
_uri: &str,
_ctx: &Context<'_>,
) -> impl Future<Output = Result<bool, McpError>> + Send {
async { Ok(false) }
}
fn unsubscribe(
&self,
_uri: &str,
_ctx: &Context<'_>,
) -> impl Future<Output = Result<bool, McpError>> + Send {
async { Ok(false) }
}
}
pub trait PromptHandler: Send + Sync {
fn list_prompts(
&self,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<Prompt>, McpError>> + Send;
fn get_prompt(
&self,
name: &str,
args: Option<serde_json::Map<String, Value>>,
ctx: &Context<'_>,
) -> impl Future<Output = Result<GetPromptResult, McpError>> + Send;
}
pub trait TaskHandler: Send + Sync {
fn list_tasks(
&self,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<Task>, McpError>> + Send;
fn get_task(
&self,
id: &TaskId,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Option<Task>, McpError>> + Send;
fn cancel_task(
&self,
id: &TaskId,
ctx: &Context<'_>,
) -> impl Future<Output = Result<bool, McpError>> + Send;
}
pub trait CompletionHandler: Send + Sync {
fn complete_resource(
&self,
partial_uri: &str,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<String>, McpError>> + Send;
fn complete_prompt_arg(
&self,
prompt_name: &str,
arg_name: &str,
partial_value: &str,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<String>, McpError>> + Send;
}
pub trait LoggingHandler: Send + Sync {
fn set_level(&self, level: LogLevel) -> impl Future<Output = Result<(), McpError>> + Send;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
pub enum LogLevel {
Debug,
#[default]
Info,
Notice,
Warning,
Error,
Critical,
Alert,
Emergency,
}
impl std::fmt::Display for LogLevel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Debug => write!(f, "debug"),
Self::Info => write!(f, "info"),
Self::Notice => write!(f, "notice"),
Self::Warning => write!(f, "warning"),
Self::Error => write!(f, "error"),
Self::Critical => write!(f, "critical"),
Self::Alert => write!(f, "alert"),
Self::Emergency => write!(f, "emergency"),
}
}
}
pub trait SamplingHandler: Send + Sync {
fn create_message(
&self,
request: CreateMessageRequest,
ctx: &Context<'_>,
) -> impl Future<Output = Result<CreateMessageResult, McpError>> + Send;
}
pub trait ElicitationHandler: Send + Sync {
fn elicit(
&self,
request: ElicitRequest,
ctx: &Context<'_>,
) -> impl Future<Output = Result<ElicitResult, McpError>> + Send;
}
use std::sync::Arc;
impl<T: ServerHandler> ServerHandler for Arc<T> {
fn server_info(&self) -> ServerInfo {
(**self).server_info()
}
fn capabilities(&self) -> ServerCapabilities {
(**self).capabilities()
}
fn instructions(&self) -> Option<String> {
(**self).instructions()
}
fn on_initialized(&self, ctx: &Context<'_>) -> impl Future<Output = ()> + Send {
(**self).on_initialized(ctx)
}
fn on_shutdown(&self) -> impl Future<Output = ()> + Send {
(**self).on_shutdown()
}
}
impl<T: ToolHandler> ToolHandler for Arc<T> {
fn list_tools(
&self,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<Tool>, McpError>> + Send {
(**self).list_tools(ctx)
}
fn call_tool(
&self,
name: &str,
args: Value,
ctx: &Context<'_>,
) -> impl Future<Output = Result<ToolOutput, McpError>> + Send {
(**self).call_tool(name, args, ctx)
}
fn on_tools_changed(&self) -> impl Future<Output = ()> + Send {
(**self).on_tools_changed()
}
}
impl<T: ResourceHandler> ResourceHandler for Arc<T> {
fn list_resources(
&self,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<Resource>, McpError>> + Send {
(**self).list_resources(ctx)
}
fn list_resource_templates(
&self,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<ResourceTemplate>, McpError>> + Send {
(**self).list_resource_templates(ctx)
}
fn read_resource(
&self,
uri: &str,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<ResourceContents>, McpError>> + Send {
(**self).read_resource(uri, ctx)
}
fn subscribe(
&self,
uri: &str,
ctx: &Context<'_>,
) -> impl Future<Output = Result<bool, McpError>> + Send {
(**self).subscribe(uri, ctx)
}
fn unsubscribe(
&self,
uri: &str,
ctx: &Context<'_>,
) -> impl Future<Output = Result<bool, McpError>> + Send {
(**self).unsubscribe(uri, ctx)
}
}
impl<T: PromptHandler> PromptHandler for Arc<T> {
fn list_prompts(
&self,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<Prompt>, McpError>> + Send {
(**self).list_prompts(ctx)
}
fn get_prompt(
&self,
name: &str,
args: Option<serde_json::Map<String, Value>>,
ctx: &Context<'_>,
) -> impl Future<Output = Result<GetPromptResult, McpError>> + Send {
(**self).get_prompt(name, args, ctx)
}
}
impl<T: TaskHandler> TaskHandler for Arc<T> {
fn list_tasks(
&self,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<Task>, McpError>> + Send {
(**self).list_tasks(ctx)
}
fn get_task(
&self,
id: &TaskId,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Option<Task>, McpError>> + Send {
(**self).get_task(id, ctx)
}
fn cancel_task(
&self,
id: &TaskId,
ctx: &Context<'_>,
) -> impl Future<Output = Result<bool, McpError>> + Send {
(**self).cancel_task(id, ctx)
}
}
impl<T: CompletionHandler> CompletionHandler for Arc<T> {
fn complete_resource(
&self,
partial_uri: &str,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<String>, McpError>> + Send {
(**self).complete_resource(partial_uri, ctx)
}
fn complete_prompt_arg(
&self,
prompt_name: &str,
arg_name: &str,
partial_value: &str,
ctx: &Context<'_>,
) -> impl Future<Output = Result<Vec<String>, McpError>> + Send {
(**self).complete_prompt_arg(prompt_name, arg_name, partial_value, ctx)
}
}
impl<T: LoggingHandler> LoggingHandler for Arc<T> {
fn set_level(&self, level: LogLevel) -> impl Future<Output = Result<(), McpError>> + Send {
(**self).set_level(level)
}
}
impl<T: SamplingHandler> SamplingHandler for Arc<T> {
fn create_message(
&self,
request: CreateMessageRequest,
ctx: &Context<'_>,
) -> impl Future<Output = Result<CreateMessageResult, McpError>> + Send {
(**self).create_message(request, ctx)
}
}
impl<T: ElicitationHandler> ElicitationHandler for Arc<T> {
fn elicit(
&self,
request: ElicitRequest,
ctx: &Context<'_>,
) -> impl Future<Output = Result<ElicitResult, McpError>> + Send {
(**self).elicit(request, ctx)
}
}
#[cfg(test)]
mod tests {
use super::*;
struct TestServer;
impl ServerHandler for TestServer {
fn server_info(&self) -> ServerInfo {
ServerInfo::new("test", "1.0.0")
}
}
#[test]
fn test_server_handler() {
let server = TestServer;
let info = server.server_info();
assert_eq!(info.name, "test");
assert_eq!(info.version, "1.0.0");
}
#[test]
fn test_log_level_ordering() {
assert!(LogLevel::Debug < LogLevel::Error);
assert!(LogLevel::Info < LogLevel::Warning);
assert!(LogLevel::Emergency > LogLevel::Alert);
}
#[test]
fn test_arc_server_handler() {
let server = Arc::new(TestServer);
let info = server.server_info();
assert_eq!(info.name, "test");
assert_eq!(info.version, "1.0.0");
}
}