use async_trait::async_trait;
use rmcp::service::{RequestContext, RoleServer};
use crate::tool::Tool;
#[async_trait]
pub trait ToolFilter: Send + Sync {
async fn allow(&self, tool: &Tool, context: &RequestContext<RoleServer>) -> bool;
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
struct AllowAll;
#[async_trait]
impl ToolFilter for AllowAll {
async fn allow(&self, _tool: &Tool, _context: &RequestContext<RoleServer>) -> bool {
true
}
}
struct BlockAll;
#[async_trait]
impl ToolFilter for BlockAll {
async fn allow(&self, _tool: &Tool, _context: &RequestContext<RoleServer>) -> bool {
false
}
}
struct PrefixFilter {
allowed_prefix: String,
}
#[async_trait]
impl ToolFilter for PrefixFilter {
async fn allow(&self, tool: &Tool, _context: &RequestContext<RoleServer>) -> bool {
tool.metadata.name.starts_with(&self.allowed_prefix)
}
}
#[test]
fn test_trait_is_object_safe() {
fn accepts_filter(_filter: &dyn ToolFilter) {}
fn accepts_arc_filter(_filter: Arc<dyn ToolFilter>) {}
let allow_all = AllowAll;
let block_all = BlockAll;
accepts_filter(&allow_all);
accepts_filter(&block_all);
accepts_arc_filter(Arc::new(AllowAll));
accepts_arc_filter(Arc::new(BlockAll));
}
#[test]
fn test_filter_can_be_cloned_via_arc() {
let filter: Arc<dyn ToolFilter> = Arc::new(AllowAll);
let _cloned = filter.clone();
}
#[test]
fn test_prefix_filter_can_be_constructed() {
let filter: Arc<dyn ToolFilter> = Arc::new(PrefixFilter {
allowed_prefix: "get".to_string(),
});
let _cloned = filter.clone();
}
}