model_context_protocol/
macro_adapter.rs1use std::sync::Arc;
7
8use serde_json::Value;
9
10use crate::protocol::McpToolDefinition;
11use crate::tool::{BoxFuture, DynTool, McpTool, ToolCallResult, ToolProvider};
12
13pub trait MacroServer: Send + Sync {
17 fn list_tools(&self) -> Vec<McpToolDefinition>;
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: McpToolDefinition,
80 server: Arc<T>,
81}
82
83impl<T: MacroServer + 'static> McpTool for MacroToolWrapper<T> {
84 fn definition(&self) -> McpToolDefinition {
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<McpToolDefinition> {
102 vec![McpToolDefinition::new("test")
103 .with_description("Test tool")
104 .with_schema(serde_json::json!({"type": "object"}))]
105 }
106
107 fn call_tool(&self, name: &str, _args: Value) -> ToolCallResult {
108 if name == "test" {
109 Ok(vec![crate::protocol::ToolContent::text("ok")])
110 } else {
111 Err(format!("Unknown: {}", name))
112 }
113 }
114 }
115
116 #[test]
117 fn test_adapter_provides_tools() {
118 let adapter = MacroServerAdapter::new(TestServer);
119 let tools = adapter.tools();
120 assert_eq!(tools.len(), 1);
121 assert_eq!(tools[0].definition().name, "test");
122 }
123}