1pub mod handler;
6pub use handler::BrowserServer;
7
8use crate::tools::{self, Tool, ToolContext, ToolResult as InternalToolResult};
9use rmcp::{
10 ErrorData as McpError,
11 handler::server::wrapper::Parameters,
12 model::{CallToolResult, Content},
13 tool, tool_router,
14};
15
16fn convert_result(result: InternalToolResult) -> Result<CallToolResult, McpError> {
18 if result.success {
19 let text = if let Some(data) = result.data {
20 serde_json::to_string_pretty(&data).unwrap_or_else(|_| data.to_string())
21 } else {
22 "Success".to_string()
23 };
24 Ok(CallToolResult::success(vec![Content::text(text)]))
25 } else {
26 let error_msg = result.error.unwrap_or_else(|| "Unknown error".to_string());
27 Err(McpError::internal_error(error_msg, None))
28 }
29}
30
31macro_rules! register_mcp_tools {
33 ($($mcp_name:ident => $tool_type:ty, $description:expr);* $(;)?) => {
34 #[tool_router]
35 impl BrowserServer {
36 $(
37 #[tool(description = $description)]
38 fn $mcp_name(
39 &self,
40 params: Parameters<<$tool_type as Tool>::Params>,
41 ) -> Result<CallToolResult, McpError> {
42 let session = self.session();
43 let mut context = ToolContext::new(&*session);
44 let tool = <$tool_type>::default();
45 let result = tool.execute_typed(params.0, &mut context)
46 .map_err(|e| McpError::internal_error(e.to_string(), None))?;
47 convert_result(result)
48 }
49 )*
50 }
51 };
52}
53
54register_mcp_tools! {
56 browser_navigate => tools::navigate::NavigateTool, "Navigate to a specified URL in the browser";
58 browser_go_back => tools::go_back::GoBackTool, "Navigate back in browser history";
59 browser_go_forward => tools::go_forward::GoForwardTool, "Navigate forward in browser history";
60 browser_close => tools::close::CloseTool, "Close the browser when the task is complete";
61
62 browser_get_text => tools::extract::ExtractContentTool, "Extract text or HTML content from the page or an element";
64 browser_get_markdown => tools::markdown::GetMarkdownTool, "Get the markdown content of the current page";
65 browser_read_links => tools::read_links::ReadLinksTool, "Read all links on the current page";
66 browser_evaluate => tools::evaluate::EvaluateTool, "Execute JavaScript code in the browser context";
67 browser_screenshot => tools::screenshot::ScreenshotTool, "Capture a screenshot of the current page";
68 browser_get_clickable_elements => tools::get_clickable_elements::GetClickableElementsTool, "Get all clickable/interactive elements on the page";
69
70 browser_click => tools::click::ClickTool, "Click on an element specified by CSS selector or index";
72 browser_hover => tools::hover::HoverTool, "Hover over an element specified by CSS selector or index";
73 browser_select => tools::select::SelectTool, "Select an option in a dropdown element by CSS selector or index";
74 browser_form_input_fill => tools::input::InputTool, "Type text into an input element";
75 browser_press_key => tools::press_key::PressKeyTool, "Press a key on the keyboard";
76 browser_scroll => tools::scroll::ScrollTool, "Scroll the page by a specified amount or to the bottom";
77 browser_wait => tools::wait::WaitTool, "Wait for an element to appear on the page";
78
79 browser_new_tab => tools::new_tab::NewTabTool, "Open a new tab and navigate to the specified URL";
81 browser_tab_list => tools::tab_list::TabListTool, "Get the list of all browser tabs with their titles and URLs";
82 browser_switch_tab => tools::switch_tab::SwitchTabTool, "Switch to a specific tab by index";
83 browser_close_tab => tools::close_tab::CloseTabTool, "Close the current active tab";
84}