use crate::mcp_pmcp::tool_functions;
use async_trait::async_trait;
use pmcp::{Error, RequestHandlerExtra, Result, ToolHandler};
use serde::Deserialize;
use serde_json::{json, Value};
use std::path::PathBuf;
use tracing::debug;
#[derive(Debug, Deserialize)]
struct QualityGateArgs {
paths: Vec<String>,
#[serde(default)]
strict: bool,
#[serde(default)]
file: Option<String>,
}
pub struct QualityGateTool;
impl QualityGateTool {
#[must_use]
pub fn new() -> Self {
Self
}
}
impl Default for QualityGateTool {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl ToolHandler for QualityGateTool {
async fn handle(&self, args: Value, _extra: RequestHandlerExtra) -> Result<Value> {
debug!("Handling quality-gate with args: {}", args);
let params: QualityGateArgs = serde_json::from_value(args)
.map_err(|e| Error::validation(format!("Invalid arguments: {e}")))?;
let paths: Vec<PathBuf> = params.paths.into_iter().map(PathBuf::from).collect();
if let Some(file_path) = params.file {
let file_path = PathBuf::from(file_path);
let result = tool_functions::check_quality_gate_file(file_path.as_ref(), params.strict)
.await
.map_err(|e| Error::internal(format!("Quality gate check failed: {e}")))?;
return Ok(result);
}
let results = tool_functions::check_quality_gates(&paths, params.strict)
.await
.map_err(|e| Error::internal(format!("Quality gate check failed: {e}")))?;
Ok(results)
}
}
#[derive(Debug, Deserialize)]
struct QualityGateSummaryArgs {
paths: Vec<String>,
#[serde(default)]
format: Option<String>,
}
pub struct QualityGateSummaryTool;
impl QualityGateSummaryTool {
#[must_use]
pub fn new() -> Self {
Self
}
}
impl Default for QualityGateSummaryTool {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl ToolHandler for QualityGateSummaryTool {
async fn handle(&self, args: Value, _extra: RequestHandlerExtra) -> Result<Value> {
debug!("Handling quality-gate.summary with args: {}", args);
let params: QualityGateSummaryArgs = serde_json::from_value(args)
.map_err(|e| Error::validation(format!("Invalid arguments: {e}")))?;
let paths: Vec<PathBuf> = params.paths.into_iter().map(PathBuf::from).collect();
let summary = tool_functions::quality_gate_summary(&paths)
.await
.map_err(|e| Error::internal(format!("Quality gate summary failed: {e}")))?;
match params.format.as_deref() {
Some("markdown") => Ok(json!({
"summary": summary,
"markdown": "Quality gate summary in markdown format (not implemented)"
})),
Some("json") | None => Ok(summary),
Some(format) => Err(Error::validation(format!("Unsupported format: {format}"))),
}
}
}
#[derive(Debug, Deserialize)]
struct QualityGateBaselineArgs {
paths: Vec<String>,
#[serde(default)]
output: Option<String>,
}
pub struct QualityGateBaselineTool;
impl QualityGateBaselineTool {
#[must_use]
pub fn new() -> Self {
Self
}
}
impl Default for QualityGateBaselineTool {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl ToolHandler for QualityGateBaselineTool {
async fn handle(&self, args: Value, _extra: RequestHandlerExtra) -> Result<Value> {
debug!("Handling quality-gate.baseline with args: {}", args);
let params: QualityGateBaselineArgs = serde_json::from_value(args)
.map_err(|e| Error::validation(format!("Invalid arguments: {e}")))?;
let paths: Vec<PathBuf> = params.paths.into_iter().map(PathBuf::from).collect();
let output_path = params.output.map(PathBuf::from);
let baseline = tool_functions::quality_gate_baseline(&paths, output_path.as_deref())
.await
.map_err(|e| Error::internal(format!("Failed to create baseline: {e}")))?;
Ok(baseline)
}
}
#[derive(Debug, Deserialize)]
struct QualityGateCompareArgs {
baseline: String,
paths: Vec<String>,
}
pub struct QualityGateCompareTool;
impl QualityGateCompareTool {
#[must_use]
pub fn new() -> Self {
Self
}
}
impl Default for QualityGateCompareTool {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl ToolHandler for QualityGateCompareTool {
async fn handle(&self, args: Value, _extra: RequestHandlerExtra) -> Result<Value> {
debug!("Handling quality-gate.compare with args: {}", args);
let params: QualityGateCompareArgs = serde_json::from_value(args)
.map_err(|e| Error::validation(format!("Invalid arguments: {e}")))?;
let baseline_path = PathBuf::from(params.baseline);
let paths: Vec<PathBuf> = params.paths.into_iter().map(PathBuf::from).collect();
let comparison = tool_functions::quality_gate_compare(baseline_path.as_ref(), &paths)
.await
.map_err(|e| Error::internal(format!("Failed to compare with baseline: {e}")))?;
Ok(comparison)
}
}
#[cfg(test)]
mod property_tests {
use proptest::prelude::*;
proptest! {
#[test]
fn basic_property_stability(_input in ".*") {
prop_assert!(true);
}
#[test]
fn module_consistency_check(_x in 0u32..1000) {
prop_assert!(_x < 1001);
}
}
}