model_context_protocol/
macro_adapter.rs1use std::sync::Arc;
7
8use serde_json::Value;
9
10use crate::protocol::McpToolDef;
11use crate::tool::{BoxFuture, DynTool, McpTool, ToolCallResult, ToolProvider};
12
13pub trait MacroServer: Send + Sync {
17 fn list_tools(&self) -> Vec<McpToolDef>;
19
20 fn call_tool(&self, name: &str, args: Value) -> ToolCallResult;
22}
23
24pub struct MacroServerAdapter<T: MacroServer> {
49 server: Arc<T>,
50}
51
52impl<T: MacroServer + 'static> MacroServerAdapter<T> {
53 pub fn new(server: T) -> Self {
55 Self {
56 server: Arc::new(server),
57 }
58 }
59}
60
61impl<T: MacroServer + 'static> ToolProvider for MacroServerAdapter<T> {
62 fn tools(&self) -> Vec<DynTool> {
63 self.server
64 .list_tools()
65 .into_iter()
66 .map(|tool_def| {
67 let wrapper = MacroToolWrapper {
68 definition: tool_def.clone(),
69 server: self.server.clone(),
70 };
71 Arc::new(wrapper) as DynTool
72 })
73 .collect()
74 }
75}
76
77struct MacroToolWrapper<T: MacroServer> {
79 definition: McpToolDef,
80 server: Arc<T>,
81}
82
83impl<T: MacroServer + 'static> McpTool for MacroToolWrapper<T> {
84 fn definition(&self) -> McpToolDef {
85 self.definition.clone()
86 }
87
88 fn call<'a>(&'a self, args: Value) -> BoxFuture<'a, ToolCallResult> {
89 let name = self.definition.name.clone();
90 Box::pin(async move { self.server.call_tool(&name, args) })
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 struct TestServer;
99
100 impl MacroServer for TestServer {
101 fn list_tools(&self) -> Vec<McpToolDef> {
102 vec![McpToolDef {
103 name: "test".to_string(),
104 description: Some("Test tool".to_string()),
105 group: None,
106 input_schema: serde_json::json!({"type": "object"}),
107 }]
108 }
109
110 fn call_tool(&self, name: &str, _args: Value) -> ToolCallResult {
111 if name == "test" {
112 Ok(vec![crate::protocol::ToolContent::text("ok")])
113 } else {
114 Err(format!("Unknown: {}", name))
115 }
116 }
117 }
118
119 #[test]
120 fn test_adapter_provides_tools() {
121 let adapter = MacroServerAdapter::new(TestServer);
122 let tools = adapter.tools();
123 assert_eq!(tools.len(), 1);
124 assert_eq!(tools[0].definition().name, "test");
125 }
126}