mcp_client_fishcode2025/
service.rs

1use futures::future::BoxFuture;
2use mcp_core_fishcode2025::protocol::JsonRpcMessage;
3use std::sync::Arc;
4use std::task::{Context, Poll};
5use tower::{timeout::Timeout, Service, ServiceBuilder};
6
7use crate::transport::{Error, TransportHandle};
8
9/// A wrapper service that implements Tower's Service trait for MCP transport
10#[derive(Clone)]
11pub struct McpService<T: TransportHandle> {
12    inner: Arc<T>,
13}
14
15impl<T: TransportHandle> McpService<T> {
16    pub fn new(transport: T) -> Self {
17        Self {
18            inner: Arc::new(transport),
19        }
20    }
21}
22
23impl<T> Service<JsonRpcMessage> for McpService<T>
24where
25    T: TransportHandle + Send + Sync + 'static,
26{
27    type Response = JsonRpcMessage;
28    type Error = Error;
29    type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
30
31    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
32        // Most transports are always ready, but this could be customized if needed
33        Poll::Ready(Ok(()))
34    }
35
36    fn call(&mut self, request: JsonRpcMessage) -> Self::Future {
37        let transport = self.inner.clone();
38        Box::pin(async move { transport.send(request).await })
39    }
40}
41
42// Add a convenience constructor for creating a service with timeout
43impl<T> McpService<T>
44where
45    T: TransportHandle,
46{
47    pub fn with_timeout(transport: T, timeout: std::time::Duration) -> Timeout<McpService<T>> {
48        ServiceBuilder::new()
49            .timeout(timeout)
50            .service(McpService::new(transport))
51    }
52}