Skip to main content

mcp_kit/server/
session.rs

1use uuid::Uuid;
2
3use crate::types::{ClientCapabilities, ClientInfo, Root};
4
5#[cfg(feature = "auth")]
6use crate::auth::AuthenticatedIdentity;
7
8/// Unique session identifier
9#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub struct SessionId(pub String);
11
12impl SessionId {
13    pub fn new() -> Self {
14        Self(Uuid::new_v4().to_string())
15    }
16}
17
18impl Default for SessionId {
19    fn default() -> Self {
20        Self::new()
21    }
22}
23
24impl std::fmt::Display for SessionId {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        write!(f, "{}", self.0)
27    }
28}
29
30/// Per-connection session data
31#[derive(Debug, Clone)]
32pub struct Session {
33    pub id: SessionId,
34    pub client_info: Option<ClientInfo>,
35    pub client_capabilities: Option<ClientCapabilities>,
36    pub protocol_version: Option<String>,
37    pub initialized: bool,
38    /// Roots declared by the client.
39    pub roots: Vec<Root>,
40    /// Populated by the transport layer after successful authentication.
41    /// `None` means the request was unauthenticated (or auth is not configured).
42    #[cfg(feature = "auth")]
43    pub identity: Option<AuthenticatedIdentity>,
44}
45
46impl Session {
47    pub fn new() -> Self {
48        Self {
49            id: SessionId::new(),
50            client_info: None,
51            client_capabilities: None,
52            protocol_version: None,
53            initialized: false,
54            roots: Vec::new(),
55            #[cfg(feature = "auth")]
56            identity: None,
57        }
58    }
59
60    /// Check if the client supports sampling.
61    pub fn supports_sampling(&self) -> bool {
62        self.client_capabilities
63            .as_ref()
64            .and_then(|c| c.sampling.as_ref())
65            .is_some()
66    }
67
68    /// Check if the client supports roots.
69    pub fn supports_roots(&self) -> bool {
70        self.client_capabilities
71            .as_ref()
72            .and_then(|c| c.roots.as_ref())
73            .map(|r| r.list_changed.unwrap_or(false))
74            .unwrap_or(false)
75    }
76}
77
78impl Default for Session {
79    fn default() -> Self {
80        Self::new()
81    }
82}