use kodegen_mcp_schema::{Tool, ToolExecutionContext, ToolArgs, ToolResponse};
use kodegen_mcp_schema::McpError;
use kodegen_mcp_schema::introspection::{InspectUsageStatsArgs, InspectUsageStatsPrompts, InspectUsageOutput, ToolUsageStats, INSPECT_USAGE_STATS};
use kodegen_utils::usage_tracker::UsageTracker;
#[derive(Clone)]
pub struct InspectUsageStatsTool {
usage_tracker: UsageTracker,
}
impl InspectUsageStatsTool {
#[must_use]
pub fn new(usage_tracker: UsageTracker) -> Self {
Self { usage_tracker }
}
}
impl Tool for InspectUsageStatsTool {
type Args = InspectUsageStatsArgs;
type Prompts = InspectUsageStatsPrompts;
fn name() -> &'static str {
INSPECT_USAGE_STATS
}
fn description() -> &'static str {
"Get usage statistics for debugging and analysis. Returns summary of tool usage, \
success/failure rates, and performance metrics."
}
async fn execute(&self, _args: Self::Args, _ctx: ToolExecutionContext) -> Result<ToolResponse<<Self::Args as ToolArgs>::Output>, McpError> {
let summary = self.usage_tracker.get_formatted_summary();
let stats = self.usage_tracker.get_stats();
let tool_usage: Vec<ToolUsageStats> = stats.tool_counts
.iter()
.map(|(name, count): (&String, &u64)| ToolUsageStats {
tool_name: name.clone(),
call_count: *count as usize,
total_duration_ms: 0, avg_duration_ms: 0, })
.collect();
let session_duration_ms = if stats.last_used > stats.first_used {
((stats.last_used - stats.first_used) * 1000) as u64
} else {
0
};
let success_rate = if stats.total_tool_calls > 0 {
(stats.successful_calls as f64 / stats.total_tool_calls as f64) * 100.0
} else {
100.0
};
let output = InspectUsageOutput {
success: true,
total_calls: stats.total_tool_calls as usize,
tools_used: stats.tool_counts.len(),
tool_usage,
session_duration_ms,
success_rate,
successful_calls: stats.successful_calls as usize,
failed_calls: stats.failed_calls as usize,
};
Ok(ToolResponse::new(summary, output))
}
fn read_only() -> bool {
true
}
fn destructive() -> bool {
false
}
fn idempotent() -> bool {
true
}
fn open_world() -> bool {
false
}
}