use crate::common::resources::{BlobTextResource, PlainTextResource, PokemonImageResource};
use super::tools::GreetingTools;
use async_trait::async_trait;
use rust_mcp_schema::{CompleteResult, ListResourceTemplatesResult, ListResourcesResult};
use rust_mcp_sdk::{
mcp_server::{enforce_compatible_protocol_version, ServerHandlerCore},
schema::{
schema_utils::CallToolError, ListToolsResult, NotificationFromClient, RequestFromClient,
ResultFromServer, RpcError,
},
McpServer,
};
use std::sync::Arc;
pub struct ExampleServerHandlerCore;
#[async_trait]
#[allow(unused)]
impl ServerHandlerCore for ExampleServerHandlerCore {
async fn handle_request(
&self,
request: RequestFromClient,
runtime: Arc<dyn McpServer>,
) -> std::result::Result<ResultFromServer, RpcError> {
let method_name = &request.method().to_owned();
match request {
RequestFromClient::InitializeRequest(params) => {
let mut server_info = runtime.server_info().to_owned();
if let Some(updated_protocol_version) = enforce_compatible_protocol_version(
¶ms.protocol_version,
&server_info.protocol_version,
)
.map_err(|err| RpcError::internal_error().with_message(err.to_string()))?
{
server_info.protocol_version = params.protocol_version;
}
return Ok(server_info.into());
}
RequestFromClient::ListToolsRequest(_params) => Ok(ListToolsResult {
meta: None,
next_cursor: None,
tools: GreetingTools::tools(),
}
.into()),
RequestFromClient::CallToolRequest(params) => {
let tool_name = params.name.to_string();
let tool_params = GreetingTools::try_from(params)
.map_err(|_| CallToolError::unknown_tool(tool_name.clone()))?;
let result = match tool_params {
GreetingTools::SayHelloTool(say_hello_tool) => say_hello_tool
.call_tool()
.map_err(|err| RpcError::internal_error().with_message(err.to_string()))?,
GreetingTools::SayGoodbyeTool(say_goodbye_tool) => say_goodbye_tool
.call_tool()
.map_err(|err| RpcError::internal_error().with_message(err.to_string()))?,
};
Ok(result.into())
}
RequestFromClient::ListResourcesRequest(params) => Ok(ListResourcesResult {
meta: None,
next_cursor: None,
resources: vec![PlainTextResource::resource(), BlobTextResource::resource()],
}
.into()),
RequestFromClient::ListResourceTemplatesRequest(params) => {
Ok(ListResourceTemplatesResult {
meta: None,
next_cursor: None,
resource_templates: vec![PokemonImageResource::resource_template()],
}
.into())
}
RequestFromClient::ReadResourceRequest(params) => {
if PlainTextResource::resource_uri().starts_with(¶ms.uri) {
return PlainTextResource::get_resource().await.map(|r| r.into());
}
if BlobTextResource::resource_uri().starts_with(¶ms.uri) {
return BlobTextResource::get_resource().await.map(|r| r.into());
}
if PokemonImageResource::matches_url(¶ms.uri) {
return PokemonImageResource::get_resource(¶ms.uri)
.await
.map(|r| r.into());
}
Err(RpcError::invalid_request()
.with_message(format!("No resource was found for '{}'.", params.uri)))
}
RequestFromClient::CompleteRequest(params) => {
if params.argument.name.eq("pokemon-id") {
Ok(CompleteResult {
completion: PokemonImageResource::completion(¶ms.argument.value),
meta: None,
}
.into())
} else {
Err(RpcError::method_not_found().with_message(format!(
"No handler is implemented for '{}'.",
params.argument.name,
)))
}
}
_ => Err(RpcError::method_not_found()
.with_message(format!("No handler is implemented for '{method_name}'.",))),
RequestFromClient::CustomRequest(_) => Err(RpcError::method_not_found()
.with_message("No handler is implemented for custom requests.".to_string())),
}
}
async fn handle_notification(
&self,
notification: NotificationFromClient,
_: Arc<dyn McpServer>,
) -> std::result::Result<(), RpcError> {
Ok(())
}
async fn handle_error(
&self,
error: &RpcError,
_: Arc<dyn McpServer>,
) -> std::result::Result<(), RpcError> {
Ok(())
}
}