diff --git a/crates/dtrack-tools/src/lib.rs b/crates/dtrack-tools/src/lib.rs index 349f381..de9c45f 100644 --- a/crates/dtrack-tools/src/lib.rs +++ b/crates/dtrack-tools/src/lib.rs @@ -54,6 +54,33 @@ pub struct LookupArg { pub version: Option, } +/// Argument fuer `suppress_finding` (SCHREIBEND). Adressiert ein Finding ueber +/// das Tripel (project, component, vulnerability) -- alle drei UUIDs stehen in +/// der `project_findings`-Antwort. +#[derive(Debug, Deserialize, JsonSchema)] +pub struct SuppressArg { + /// UUID des Projekts. + pub project: String, + /// UUID der betroffenen Komponente. + pub component: String, + /// UUID der Schwachstelle (vulnerability). + pub vulnerability: String, + /// `true` = unterdruecken (Default), `false` = Unterdrueckung aufheben. + #[serde(default)] + pub suppressed: Option, + /// Optionaler Analyse-Status (DT-Enum: `FALSE_POSITIVE`, `NOT_AFFECTED`, + /// `RESOLVED`, `EXPLOITABLE`, `IN_TRIAGE`, `NOT_SET`). + #[serde(default)] + pub state: Option, + /// Optionale Begruendung (DT-Enum, z.B. `CODE_NOT_REACHABLE`, + /// `CODE_NOT_PRESENT`, `REQUIRES_CONFIGURATION`). Passt zu `NOT_AFFECTED`. + #[serde(default)] + pub justification: Option, + /// Optionaler Kommentar fuer den Audit-Trail. Dringend empfohlen. + #[serde(default)] + pub comment: Option, +} + #[tool_router] impl DtrackServer { pub fn new(client: SharedClient) -> Self { @@ -163,6 +190,27 @@ impl DtrackServer { .map_err(|e| McpError::internal_error(e.to_string(), None))?; Ok(CallToolResult::success(vec![Content::text(body)])) } + + #[tool(description = "SCHREIBEND: setzt Suppression/Analyse fuer ein Finding (project+component+vulnerability UUIDs aus project_findings). suppressed default true; optional state/justification/comment. Braucht das DT-Recht VULNERABILITY_ANALYSIS.")] + async fn suppress_finding( + &self, + Parameters(arg): Parameters, + ) -> Result { + let client = self.client.read().await.clone(); + let body = client + .set_analysis( + &arg.project, + &arg.component, + &arg.vulnerability, + Some(arg.suppressed.unwrap_or(true)), + arg.state.as_deref(), + arg.justification.as_deref(), + arg.comment.as_deref(), + ) + .await + .map_err(|e| McpError::internal_error(e.to_string(), None))?; + Ok(CallToolResult::success(vec![Content::text(body)])) + } } #[tool_handler] @@ -173,8 +221,9 @@ impl ServerHandler for DtrackServer { capabilities: ServerCapabilities::builder().enable_tools().build(), server_info: Implementation::from_build_env(), instructions: Some( - "Read-only Zugriff auf Dependency-Track: Projekte (Liste/Lookup), \ - Komponenten, Findings, Metriken, Policy-Verstoesse, VEX und SBOM (CycloneDX)." + "Dependency-Track-Zugriff: lesend (Projekte Liste/Lookup, Komponenten, \ + Findings, Metriken, Policy-Verstoesse, VEX, SBOM) plus eine Schreib-Operation \ + (suppress_finding: Suppression/Analyse setzen, braucht VULNERABILITY_ANALYSIS)." .to_string(), ), }