diff --git a/crates/dtrack-stdio/src/main.rs b/crates/dtrack-stdio/src/main.rs index 34bfac2..fbbdaa5 100644 --- a/crates/dtrack-stdio/src/main.rs +++ b/crates/dtrack-stdio/src/main.rs @@ -1,93 +1,7 @@ use anyhow::Result; -use dtrack_core::DtrackClient; -use rmcp::{ - handler::server::router::tool::ToolRouter, - handler::server::wrapper::Parameters, - model::{ - CallToolResult, Content, Implementation, ProtocolVersion, ServerCapabilities, ServerInfo, - }, - tool, tool_handler, tool_router, - transport::stdio, - ErrorData as McpError, ServerHandler, ServiceExt, -}; -use schemars::JsonSchema; -use serde::Deserialize; - -/// MCP-Server fuer Dependency-Track. Haelt den DT-Client + den vom Macro -/// generierten ToolRouter. -#[derive(Clone)] -pub struct DtrackServer { - client: DtrackClient, - tool_router: ToolRouter, -} - -/// Argument fuer projektbezogene Tools. -#[derive(Debug, Deserialize, JsonSchema)] -pub struct ProjectArg { - /// UUID des Projekts (aus `list_projects`). - pub uuid: String, -} - -#[tool_router] -impl DtrackServer { - pub fn new(client: DtrackClient) -> Self { - Self { - client, - tool_router: Self::tool_router(), - } - } - - #[tool(description = "Listet aktive Dependency-Track-Projekte auf (Name, Version, UUID).")] - async fn list_projects(&self) -> Result { - let body = self - .client - .list_projects() - .await - .map_err(|e| McpError::internal_error(e.to_string(), None))?; - Ok(CallToolResult::success(vec![Content::text(body)])) - } - - #[tool(description = "Findings (Schwachstellen) eines Projekts anhand seiner UUID.")] - async fn project_findings( - &self, - Parameters(arg): Parameters, - ) -> Result { - let body = self - .client - .project_findings(&arg.uuid) - .await - .map_err(|e| McpError::internal_error(e.to_string(), None))?; - Ok(CallToolResult::success(vec![Content::text(body)])) - } - - #[tool(description = "Aktuelle Sicherheits-Metriken eines Projekts anhand seiner UUID.")] - async fn project_metrics( - &self, - Parameters(arg): Parameters, - ) -> Result { - let body = self - .client - .project_metrics(&arg.uuid) - .await - .map_err(|e| McpError::internal_error(e.to_string(), None))?; - Ok(CallToolResult::success(vec![Content::text(body)])) - } -} - -#[tool_handler] -impl ServerHandler for DtrackServer { - fn get_info(&self) -> ServerInfo { - ServerInfo { - protocol_version: ProtocolVersion::V_2025_06_18, - capabilities: ServerCapabilities::builder().enable_tools().build(), - server_info: Implementation::from_build_env(), - instructions: Some( - "Read-only Zugriff auf Dependency-Track (Projekte, Findings, Metriken)." - .to_string(), - ), - } - } -} +use dtrack_core::{DtrackClient, DtrackConfig}; +use dtrack_tools::DtrackServer; +use rmcp::{transport::stdio, ServiceExt}; #[tokio::main] async fn main() -> Result<()> { @@ -98,7 +12,10 @@ async fn main() -> Result<()> { .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) .init(); - let client = DtrackClient::from_env()?; + // Config: Datei (DTRACK_CONFIG) hat Vorrang, sonst Umgebungsvariablen. + let cfg = DtrackConfig::resolve()?; + let client = DtrackClient::from_config(&cfg)?; + let service = DtrackServer::new(client).serve(stdio()).await?; service.waiting().await?; Ok(())