Skip to main content

systemprompt_models/mcp/
client_profile.rs

1//! Negotiated MCP client identity used to shape tool results per client.
2//!
3//! [`ClientProfile`] captures what a connected client declared during
4//! `initialize`: its protocol version, implementation name, and negotiated
5//! extension keys. The response builder consults it to decide which wire
6//! pieces a client can accept — embedded UI resources, `structuredContent`,
7//! and custom `_meta`. An absent or unparseable declaration yields
8//! [`ClientProfile::unknown`], which downgrades the result to the
9//! plain-text shape every conforming client accepts.
10//!
11//! Copyright (c) systemprompt.io — Business Source License 1.1.
12//! See <https://systemprompt.io> for licensing details.
13
14use rmcp::model::{InitializeRequestParams, ProtocolVersion};
15use std::collections::BTreeSet;
16
17use super::capabilities::McpExtensionId;
18
19#[derive(Debug, Clone, Default, PartialEq, Eq)]
20pub struct ClientProfile {
21    pub protocol_version: Option<ProtocolVersion>,
22    pub client_name: Option<String>,
23    pub extensions: BTreeSet<String>,
24}
25
26impl ClientProfile {
27    #[must_use]
28    pub fn unknown() -> Self {
29        Self::default()
30    }
31
32    #[must_use]
33    pub fn from_initialize_params(params: &InitializeRequestParams) -> Self {
34        Self {
35            protocol_version: Some(params.protocol_version.clone()),
36            client_name: Some(params.client_info.name.clone()),
37            extensions: params
38                .capabilities
39                .extensions
40                .as_ref()
41                .map(|exts| exts.keys().cloned().collect())
42                .unwrap_or_default(),
43        }
44    }
45
46    #[must_use]
47    pub fn supports_ui(&self) -> bool {
48        self.extensions.contains(McpExtensionId::McpAppsUi.as_str())
49    }
50
51    #[must_use]
52    pub fn supports_structured_content(&self) -> bool {
53        self.protocol_version
54            .as_ref()
55            .is_some_and(|v| *v >= ProtocolVersion::V_2025_06_18)
56    }
57}