Skip to main content
Glama

CodeGraph CLI MCP Server

by Jakedismo
agentic_schemas.rs13.9 kB
// ABOUTME: JSON schemas for structured agentic tool outputs enforcing file paths // ABOUTME: Combines freeform analysis with structured component/dependency data use schemars::{schema_for, JsonSchema}; use serde::{Deserialize, Serialize}; use serde_json::Value; use crate::llm_provider::{JsonSchema as LLMJsonSchema, ResponseFormat}; /// Common file location reference with line number #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct FileLocation { /// Component/symbol name pub name: String, /// Absolute or relative file path pub file_path: String, /// Line number where the component is defined pub line_number: Option<usize>, /// Optional brief description of the component's role pub description: Option<String>, } /// Dependency relationship between two components #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct DependencyLink { /// Source component name pub from_name: String, /// Source file location pub from_file: String, /// Source line number pub from_line: Option<usize>, /// Target component name pub to_name: String, /// Target file location pub to_file: String, /// Target line number pub to_line: Option<usize>, /// Dependency type (e.g., "import", "call", "extends") pub dependency_type: String, } /// Structured output for agentic_code_search #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct CodeSearchOutput { /// Natural language analysis of search results pub analysis: String, /// Relevant code components found pub components: Vec<FileLocation>, /// Key patterns or insights discovered pub patterns: Vec<String>, } /// Structured output for agentic_dependency_analysis #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct DependencyAnalysisOutput { /// Natural language dependency analysis pub analysis: String, /// Components involved in the dependency graph pub components: Vec<FileLocation>, /// Dependency relationships (flexible: can be strings or DependencyLink objects) pub dependencies: Vec<serde_json::Value>, /// Circular dependencies detected (if any) pub circular_dependencies: Vec<Vec<String>>, /// Depth of dependency tree analyzed pub max_depth_analyzed: usize, } /// Call chain step in execution flow #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct CallChainStep { /// Step number in the call chain pub step: usize, /// Function/method name pub function_name: String, /// File location pub file_path: String, /// Line number pub line_number: Option<usize>, /// What this step does pub action: String, } /// Structured output for agentic_call_chain_analysis #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct CallChainOutput { /// Natural language analysis of execution flow pub analysis: String, /// Entry point of the call chain pub entry_point: FileLocation, /// Ordered call chain steps (flexible: can be strings or CallChainStep objects) pub call_chain: Vec<serde_json::Value>, /// Key decision points or branches (flexible: can be strings or FileLocation objects) pub decision_points: Vec<serde_json::Value>, } /// Architecture layer in the system #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct ArchitectureLayer { /// Layer name (e.g., "Presentation", "Business Logic", "Data Access") pub name: String, /// Components in this layer pub components: Vec<FileLocation>, /// Responsibilities of this layer pub responsibilities: Vec<String>, } /// Coupling metric for a component #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct CouplingMetric { /// Component being measured pub component: FileLocation, /// Afferent coupling (incoming dependencies) pub afferent_coupling: usize, /// Efferent coupling (outgoing dependencies) pub efferent_coupling: usize, /// Instability metric (efferent / (afferent + efferent)) pub instability: f64, } /// Structured output for agentic_architecture_analysis #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct ArchitectureAnalysisOutput { /// Natural language architecture analysis pub analysis: String, /// Architectural layers identified (flexible: can be strings or ArchitectureLayer objects) pub layers: Vec<serde_json::Value>, /// Hub nodes (highly connected components) pub hub_nodes: Vec<FileLocation>, /// Coupling metrics (flexible: can be strings or CouplingMetric objects) pub coupling_metrics: Vec<serde_json::Value>, /// Architectural patterns detected pub patterns: Vec<String>, /// Architectural issues or smells pub issues: Vec<String>, } /// Public API endpoint or interface #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct APIEndpoint { /// Function/class/interface name pub name: String, /// File location pub file_path: String, /// Line number pub line_number: Option<usize>, /// API type (e.g., "HTTP endpoint", "public function", "exported class") pub api_type: String, /// Brief description of what it does pub description: String, /// Dependencies this endpoint relies on pub dependencies: Vec<String>, } /// Structured output for agentic_api_surface_analysis #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct APISurfaceOutput { /// Natural language API surface analysis pub analysis: String, /// Public API endpoints/interfaces (flexible: can be simplified objects) pub endpoints: Vec<serde_json::Value>, /// API usage patterns pub usage_patterns: Vec<String>, /// Integration points with external systems (flexible: can be strings or FileLocation objects) pub integration_points: Vec<serde_json::Value>, } /// Structured output for agentic_context_builder #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct ContextBuilderOutput { /// Natural language context summary pub analysis: String, /// Core components in this context pub core_components: Vec<FileLocation>, /// Dependency tree structure (flexible: can be simplified) pub dependency_tree: serde_json::Value, /// Execution flows (flexible: can be simplified) pub execution_flows: Vec<serde_json::Value>, /// Architectural context (flexible: can be simplified) pub architecture: serde_json::Value, /// Related documentation or comments pub documentation_references: Vec<String>, } /// Structured output for agentic_semantic_question #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct SemanticQuestionOutput { /// Direct answer to the question pub answer: String, /// Supporting evidence with file locations pub evidence: Vec<FileLocation>, /// Related components that provide context pub related_components: Vec<FileLocation>, /// Confidence level (0.0 to 1.0) pub confidence: f64, } /// Structured output for agentic_complexity_analysis #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct ComplexityAnalysisOutput { /// Natural language analysis of complexity hotspots pub analysis: String, /// Top complexity hotspots with risk scores pub hotspots: Vec<FileLocation>, /// Refactoring recommendations prioritized by risk reduction pub refactoring_roadmap: Vec<serde_json::Value>, /// Pattern detection results (cycles, god objects, etc.) pub patterns_detected: Vec<String>, /// Risk statistics summary pub risk_summary: serde_json::Value, } /// Unified output type for all agentic tools #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] #[serde(tag = "type", rename_all = "snake_case")] pub enum AgenticOutput { CodeSearch(CodeSearchOutput), DependencyAnalysis(DependencyAnalysisOutput), CallChain(CallChainOutput), ArchitectureAnalysis(ArchitectureAnalysisOutput), APISurface(APISurfaceOutput), ContextBuilder(ContextBuilderOutput), SemanticQuestion(SemanticQuestionOutput), ComplexityAnalysis(ComplexityAnalysisOutput), } impl AgenticOutput { /// Get the natural language analysis from any output type pub fn analysis(&self) -> &str { match self { Self::CodeSearch(o) => &o.analysis, Self::DependencyAnalysis(o) => &o.analysis, Self::CallChain(o) => &o.analysis, Self::ArchitectureAnalysis(o) => &o.analysis, Self::APISurface(o) => &o.analysis, Self::ContextBuilder(o) => &o.analysis, Self::SemanticQuestion(o) => &o.answer, Self::ComplexityAnalysis(o) => &o.analysis, } } /// Extract all file locations from any output type pub fn all_file_locations(&self) -> Vec<&FileLocation> { match self { Self::CodeSearch(o) => o.components.iter().collect(), Self::DependencyAnalysis(o) => o.components.iter().collect(), Self::CallChain(o) => { // Only extract entry_point (direct FileLocation) // decision_points are now flexible Value types vec![&o.entry_point] } Self::ArchitectureAnalysis(o) => { // Only extract hub_nodes (direct FileLocation array) // layers and coupling_metrics are now flexible Value types o.hub_nodes.iter().collect() } Self::APISurface(_) => { // integration_points are now flexible Value types, can't extract directly vec![] } Self::ContextBuilder(o) => { // Only extract core_components (direct FileLocation array) // dependency_tree, execution_flows, architecture are now flexible Value types o.core_components.iter().collect() } Self::SemanticQuestion(o) => { let mut locs = o.evidence.iter().collect::<Vec<_>>(); locs.extend(o.related_components.iter()); locs } Self::ComplexityAnalysis(o) => { // Extract hotspots which are FileLocations o.hotspots.iter().collect() } } } } /// Helper to convert schemars schema to JSON value fn schema_to_json_value<T: JsonSchema>() -> Value { let schema = schema_for!(T); serde_json::to_value(schema).expect("Failed to serialize schema") } /// Generate ResponseFormat for code search pub fn code_search_response_format() -> ResponseFormat { ResponseFormat::JsonSchema { json_schema: LLMJsonSchema { name: "code_search_output".to_string(), schema: schema_to_json_value::<CodeSearchOutput>(), strict: true, }, } } /// Generate ResponseFormat for dependency analysis pub fn dependency_analysis_response_format() -> ResponseFormat { ResponseFormat::JsonSchema { json_schema: LLMJsonSchema { name: "dependency_analysis_output".to_string(), schema: schema_to_json_value::<DependencyAnalysisOutput>(), strict: true, }, } } /// Generate ResponseFormat for call chain analysis pub fn call_chain_response_format() -> ResponseFormat { ResponseFormat::JsonSchema { json_schema: LLMJsonSchema { name: "call_chain_output".to_string(), schema: schema_to_json_value::<CallChainOutput>(), strict: true, }, } } /// Generate ResponseFormat for architecture analysis pub fn architecture_analysis_response_format() -> ResponseFormat { ResponseFormat::JsonSchema { json_schema: LLMJsonSchema { name: "architecture_analysis_output".to_string(), schema: schema_to_json_value::<ArchitectureAnalysisOutput>(), strict: true, }, } } /// Generate ResponseFormat for API surface analysis pub fn api_surface_response_format() -> ResponseFormat { ResponseFormat::JsonSchema { json_schema: LLMJsonSchema { name: "api_surface_output".to_string(), schema: schema_to_json_value::<APISurfaceOutput>(), strict: true, }, } } /// Generate ResponseFormat for context builder pub fn context_builder_response_format() -> ResponseFormat { ResponseFormat::JsonSchema { json_schema: LLMJsonSchema { name: "context_builder_output".to_string(), schema: schema_to_json_value::<ContextBuilderOutput>(), strict: true, }, } } /// Generate ResponseFormat for semantic question pub fn semantic_question_response_format() -> ResponseFormat { ResponseFormat::JsonSchema { json_schema: LLMJsonSchema { name: "semantic_question_output".to_string(), schema: schema_to_json_value::<SemanticQuestionOutput>(), strict: true, }, } } #[cfg(test)] mod tests { use super::*; // FIXME: These tests need updating for current schemars API // #[test] // fn test_code_search_schema() { // let root_schema = schemars::schema_for!(CodeSearchOutput); // // Schema validation tests disabled - schemars API changed // } // #[test] // fn test_file_location_required_fields() { // let root_schema = schemars::schema_for!(FileLocation); // // Schema validation tests disabled - schemars API changed // } #[test] fn test_analysis_extraction() { let output = AgenticOutput::CodeSearch(CodeSearchOutput { analysis: "Test analysis".to_string(), components: vec![], patterns: vec![], }); assert_eq!(output.analysis(), "Test analysis"); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Jakedismo/codegraph-rust'

If you have feedback or need assistance with the MCP directory API, please join our Discord server