pub mod health; pub mod tests; use rmcp::tool; use rmcp::model::{ServerCapabilities, ServerInfo}; use rmcp::ServerHandler; use sqlx::SqlitePool; use tracing::instrument; use crate::config::Config; #[derive(Clone)] pub struct PomServer { pub pool: SqlitePool, pub config: Config, } impl PomServer { pub fn new(pool: SqlitePool, config: Config) -> Self { Self { pool, config } } } #[tool(tool_box)] impl PomServer { /// Get overall status dashboard for all configured targets. #[tool(description = "Get overall status dashboard: all targets' latest health check and test run results. Use this for a quick overview.")] #[instrument(skip_all)] pub async fn get_status(&self) -> String { match self.get_status_impl().await { Ok(result) => result, Err(e) => format!("Error getting status: {e}"), } } /// Check health of a target (or all targets). #[tool(description = "Run a live health check against a target's health endpoint. Stores the result and returns the snapshot. Omit target to check all.")] #[instrument(skip_all)] pub async fn check_health( &self, #[tool(aggr)] params: health::CheckHealthParams, ) -> String { match self.check_health_impl(params).await { Ok(result) => result, Err(e) => format!("Error checking health: {e}"), } } /// Get health check history. #[tool(description = "Get recent health check history. Optionally filter by target and limit results (default 10).")] #[instrument(skip_all)] pub async fn health_history( &self, #[tool(aggr)] params: health::HealthHistoryParams, ) -> String { match self.health_history_impl(params).await { Ok(result) => result, Err(e) => format!("Error getting health history: {e}"), } } /// List configured targets. #[tool(description = "List all configured targets with their labels and capabilities (health check, test suite).")] #[instrument(skip_all)] pub async fn list_targets(&self) -> String { match self.list_targets_impl().await { Ok(result) => result, Err(e) => format!("Error listing targets: {e}"), } } /// Run tests on a target via SSH. #[tool(description = "Run the test suite on a target via SSH. Returns a summary with pass/fail counts. Optionally provide a filter to run specific tests.")] #[instrument(skip_all)] pub async fn run_tests( &self, #[tool(aggr)] params: tests::RunTestsParams, ) -> String { match self.run_tests_impl(params).await { Ok(result) => result, Err(e) => format!("Error running tests: {e}"), } } /// Get test run history. #[tool(description = "Get recent test run history (without raw output). Optionally filter by target and limit results (default 10).")] #[instrument(skip_all)] pub async fn test_history( &self, #[tool(aggr)] params: tests::TestHistoryParams, ) -> String { match self.test_history_impl(params).await { Ok(result) => result, Err(e) => format!("Error getting test history: {e}"), } } /// Get raw output of the most recent test run. #[tool(description = "Get the full raw stdout/stderr output of the most recent test run for a target. Useful for debugging failures.")] #[instrument(skip_all)] pub async fn last_test_output( &self, #[tool(aggr)] params: tests::LastTestOutputParams, ) -> String { match self.last_test_output_impl(params).await { Ok(result) => result, Err(e) => format!("Error getting test output: {e}"), } } /// Get peer mesh status. #[tool(description = "Get the peer mesh status showing all PoM instances, their connectivity, versions, and target health. Requires serve mode to be running.")] #[instrument(skip_all)] pub async fn get_mesh_status(&self) -> String { match self.get_mesh_status_impl().await { Ok(result) => result, Err(e) => format!("Error getting mesh status: {e}"), } } } #[tool(tool_box)] impl ServerHandler for PomServer { fn get_info(&self) -> ServerInfo { ServerInfo { instructions: Some( "Peace of Mind (PoM) server for monitoring production health and running tests. \ Tools: get_status (dashboard), check_health (live health check), health_history, \ list_targets, run_tests (SSH test execution), test_history, last_test_output, \ get_mesh_status (peer mesh overview)." .into(), ), capabilities: ServerCapabilities::builder().enable_tools().build(), ..Default::default() } } }