use rmcp::model::ToolAnnotations;
use strum::AsRefStr;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, AsRefStr)]
pub enum ToolCategory {
#[strum(serialize = "App")]
App,
#[strum(serialize = "Component")]
Component,
#[strum(serialize = "Discovery")]
Discovery,
#[strum(serialize = "Dynamic BRP")]
DynamicBrp,
#[strum(serialize = "Entity")]
Entity,
#[strum(serialize = "Event")]
Event,
#[strum(serialize = "Extras")]
Extras,
#[strum(serialize = "Logging")]
Logging,
#[strum(serialize = "Resource")]
Resource,
#[strum(serialize = "Watch")]
Watch,
#[strum(serialize = "Watch Monitoring")]
WatchMonitoring,
}
#[derive(Debug, Clone)]
pub struct Annotation {
pub title: String,
pub tool_category: ToolCategory,
pub environment_impact: EnvironmentImpact,
pub domain_of_interaction: DomainOfInteraction,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EnvironmentImpact {
ReadOnly,
DestructiveIdempotent,
DestructiveNonIdempotent,
AdditiveIdempotent,
AdditiveNonIdempotent,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DomainOfInteraction {
OpenWorld,
LocalOnly,
}
impl Annotation {
pub(super) fn new(
title: impl Into<String>,
tool_category: ToolCategory,
environment_impact: EnvironmentImpact,
) -> Self {
Self {
title: title.into(),
tool_category,
environment_impact,
domain_of_interaction: DomainOfInteraction::LocalOnly, }
}
}
impl From<Annotation> for ToolAnnotations {
fn from(brp: Annotation) -> Self {
let (read_only, destructive, idempotent) = match brp.environment_impact {
EnvironmentImpact::ReadOnly => (Some(true), None, None),
EnvironmentImpact::DestructiveIdempotent | EnvironmentImpact::AdditiveIdempotent => {
(Some(false), Some(true), Some(true))
},
EnvironmentImpact::DestructiveNonIdempotent
| EnvironmentImpact::AdditiveNonIdempotent => (Some(false), Some(true), Some(false)),
};
let open_world = match brp.domain_of_interaction {
DomainOfInteraction::OpenWorld => Some(true),
DomainOfInteraction::LocalOnly => Some(false),
};
Self::from_raw(
Some(brp.title),
read_only,
destructive,
idempotent,
open_world,
)
}
}