1use network_interface::{NetworkInterface, NetworkInterfaceConfig, Addr};
2use rmcp::{
3 handler::server::{router::tool::ToolRouter, ServerHandler},
4 model::*,
5 ErrorData as McpError,
6};
7
8#[derive(Debug)]
9pub struct NetworkServer {
10 pub tool_router: ToolRouter<Self>,
11}
12
13impl Default for NetworkServer {
14 fn default() -> Self {
15 Self::new()
16 }
17}
18
19impl NetworkServer {
20 pub fn new() -> Self {
21 Self {
22 tool_router: Self::tool_router(),
23 }
24 }
25
26 fn format_interfaces(interfaces: &[NetworkInterface]) -> String {
27 let mut result = String::from("Network Interfaces:\n\n");
28
29 if interfaces.is_empty() {
30 result.push_str("No network interfaces found.\n");
31 return result;
32 }
33
34 for iface in interfaces {
35 let is_loopback = iface.addr.iter().any(|a| match a {
37 Addr::V4(v4) => v4.ip.is_loopback(),
38 Addr::V6(v6) => v6.ip.is_loopback(),
39 });
40
41 result.push_str(&format!("{}", iface.name));
42 if is_loopback {
43 result.push_str(" (loopback)");
44 }
45 result.push('\n');
46
47 if let Some(ref mac) = iface.mac_addr {
49 if !mac.is_empty() && mac != "00:00:00:00:00:00" {
50 result.push_str(&format!(" MAC: {}\n", mac));
51 }
52 }
53
54 for addr in &iface.addr {
56 match addr {
57 Addr::V4(v4) => {
58 result.push_str(&format!(" IPv4: {}", v4.ip));
59 if let Some(netmask) = &v4.netmask {
60 result.push_str(&format!(" / {}", netmask));
61 }
62 result.push('\n');
63 }
64 Addr::V6(v6) => {
65 if !v6.ip.to_string().starts_with("fe80") {
67 result.push_str(&format!(" IPv6: {}\n", v6.ip));
68 }
69 }
70 }
71 }
72
73 result.push('\n');
74 }
75
76 let active_count = interfaces.iter()
78 .filter(|i| !i.addr.is_empty())
79 .count();
80 result.push_str(&format!("Total interfaces: {} ({} with addresses)\n",
81 interfaces.len(), active_count));
82
83 result
84 }
85}
86
87#[rmcp::tool_router]
88impl NetworkServer {
89 #[rmcp::tool(description = "List all network interfaces with their IP addresses and MAC addresses")]
90 pub async fn get_interfaces(&self) -> Result<CallToolResult, McpError> {
91 let interfaces = NetworkInterface::show()
92 .map_err(|e| McpError::internal_error(format!("Failed to get network interfaces: {}", e), None))?;
93
94 let formatted = Self::format_interfaces(&interfaces);
95
96 Ok(CallToolResult::success(vec![Content::text(formatted)]))
97 }
98}
99
100#[rmcp::tool_handler]
101impl ServerHandler for NetworkServer {
102 fn get_info(&self) -> ServerInfo {
103 ServerInfo {
104 protocol_version: ProtocolVersion::V_2024_11_05,
105 capabilities: ServerCapabilities::builder()
106 .enable_tools()
107 .build(),
108 server_info: Implementation::from_build_env(),
109 instructions: Some("Cross-platform network interface information server".into()),
110 }
111 }
112}