mod session_id;
use std::future::Future;
use thiserror::Error;
pub use self::session_id::{HTTP_SESSION_ID_HEADER, McpSessionId, ParseSessionIdError};
use crate::{ParseError, ProtocolError, ToolOutput, ToolRegistry};
pub trait ToolHandler<R: ToolRegistry>: Send + Sync {
type Error: std::fmt::Display;
fn handle(
&self,
session_id: Option<McpSessionId>,
tool: R,
) -> impl Future<Output = Result<ToolOutput, Self::Error>> + Send;
}
impl<R, F, Fut, T, E> ToolHandler<R> for F
where
R: ToolRegistry + Send,
F: Fn(Option<McpSessionId>, R) -> Fut + Send + Sync,
Fut: Future<Output = Result<T, E>> + Send,
T: Into<ToolOutput>,
E: std::fmt::Display,
{
type Error = E;
async fn handle(&self, session_id: Option<McpSessionId>, tool: R) -> Result<ToolOutput, E> {
self(session_id, tool).await.map(Into::into)
}
}
pub trait MutToolHandler<R: ToolRegistry> {
type Error: std::fmt::Display;
fn handle(
&mut self,
session_id: Option<McpSessionId>,
tool: R,
) -> impl Future<Output = Result<ToolOutput, Self::Error>> + Send;
}
impl<R: ToolRegistry, T: ToolHandler<R>> MutToolHandler<R> for T {
type Error = <T as ToolHandler<R>>::Error;
fn handle(
&mut self,
session_id: Option<McpSessionId>,
tool: R,
) -> impl Future<Output = Result<ToolOutput, Self::Error>> + Send {
ToolHandler::handle(self, session_id, tool)
}
}
#[cfg(feature = "io-stdlib")]
#[cfg_attr(docsrs, doc(cfg(feature = "io-stdlib")))]
pub mod stdlib;
#[cfg(feature = "io-tokio")]
#[cfg_attr(docsrs, doc(cfg(feature = "io-tokio")))]
pub mod tokio;
#[cfg(feature = "io-axum")]
#[cfg_attr(docsrs, doc(cfg(feature = "io-axum")))]
pub mod axum;
#[derive(Debug, Error)]
pub enum IoError {
#[error("IO error")]
Io(#[source] std::io::Error),
#[error("failed to serialize message")]
Serialize(#[source] serde_json::Error),
#[error("failed to parse message")]
Parse(#[source] ParseError),
#[error("protocol error")]
Protocol(#[source] ProtocolError),
}