Skip to main content
Glama

CodeAnalysis MCP Server

by 0xjcf
visualize.py8.66 kB
#!/usr/bin/env python3 # MEMORY_ANCHOR: knowledge_graph_visualization """Knowledge Graph Visualization This script visualizes the knowledge graph generated by generator.py. Maturity: beta Why: Visualization helps developers understand the relationships between components, making it easier to navigate the codebase and identify dependencies or potential issues. """ import json import argparse import networkx as nx import matplotlib.pyplot as plt from pathlib import Path import matplotlib.patches as mpatches # Define paths BASE_DIR = Path(__file__).parent.parent GRAPH_FILE = BASE_DIR / "knowledge_graph" / "graph.json" OUTPUT_DIR = BASE_DIR / "knowledge_graph" / "visualizations" # Define node colors by type NODE_COLORS = { "component": "#4285F4", # Blue "file": "#34A853", # Green "function": "#FBBC05", # Yellow "class": "#EA4335", # Red "error": "#FF6D00", # Orange "solution": "#00C853", # Green "pattern": "#AA00FF", # Purple "concept": "#6200EA" # Deep Purple } # Define edge colors by type EDGE_COLORS = { "depends_on": "#4285F4", # Blue "imports": "#34A853", # Green "calls": "#FBBC05", # Yellow "inherits_from": "#EA4335", # Red "contains": "#9E9E9E", # Grey "causes": "#FF6D00", # Orange "solves": "#00C853", # Green "implements": "#AA00FF", # Purple "references": "#6200EA" # Deep Purple } def load_knowledge_graph(file_path): """Load the knowledge graph from a file.""" try: with open(file_path, 'r') as f: return json.load(f) except Exception as e: print(f"Error loading knowledge graph: {e}") return None def create_graph(knowledge_graph): """Create a NetworkX graph from the knowledge graph.""" G = nx.DiGraph() # Add nodes for node in knowledge_graph.get("nodes", []): node_id = node.get("id") node_type = node.get("type") node_name = node.get("name", "") if node_id: G.add_node(node_id, type=node_type, name=node_name, maturity=node.get("maturity"), description=node.get("description", "")) # Add edges for edge in knowledge_graph.get("edges", []): source = edge.get("source") target = edge.get("target") edge_type = edge.get("type") if source and target: G.add_edge(source, target, type=edge_type) return G def visualize_full_graph(G, output_file): """Visualize the full knowledge graph.""" plt.figure(figsize=(20, 20)) # Set node colors based on type node_colors = [NODE_COLORS.get(G.nodes[node].get("type"), "#9E9E9E") for node in G.nodes] # Set edge colors based on type edge_colors = [EDGE_COLORS.get(G.edges[edge].get("type"), "#9E9E9E") for edge in G.edges] # Create layout pos = nx.spring_layout(G, k=0.15, iterations=50) # Draw nodes nx.draw_networkx_nodes(G, pos, node_size=300, node_color=node_colors, alpha=0.8) # Draw edges nx.draw_networkx_edges(G, pos, width=1, alpha=0.5, edge_color=edge_colors, arrows=True, arrowsize=10) # Draw labels nx.draw_networkx_labels(G, pos, font_size=8, font_family="sans-serif") # Create legend for node types node_patches = [mpatches.Patch(color=color, label=node_type) for node_type, color in NODE_COLORS.items()] plt.legend(handles=node_patches, title="Node Types", loc="upper left", bbox_to_anchor=(1, 1)) plt.axis("off") plt.title("Knowledge Graph Visualization") plt.tight_layout() plt.savefig(output_file, dpi=300, bbox_inches="tight") plt.close() print(f"Full graph visualization saved to {output_file}") def visualize_component_dependencies(G, output_file): """Visualize component dependencies.""" # Create a subgraph with only component nodes and depends_on edges component_nodes = [node for node in G.nodes if G.nodes[node].get("type") == "component"] SG = G.subgraph(component_nodes) # Filter edges to only include depends_on depends_on_edges = [(u, v) for u, v, data in SG.edges(data=True) if data.get("type") == "depends_on"] # Create a new graph with only the filtered edges DG = nx.DiGraph() for node in component_nodes: DG.add_node(node, **G.nodes[node]) for u, v in depends_on_edges: DG.add_edge(u, v, type="depends_on") plt.figure(figsize=(15, 15)) # Set node colors node_colors = [NODE_COLORS.get("component") for _ in DG.nodes] # Create layout pos = nx.spring_layout(DG, k=0.3, iterations=50) # Draw nodes nx.draw_networkx_nodes(DG, pos, node_size=500, node_color=node_colors, alpha=0.8) # Draw edges nx.draw_networkx_edges(DG, pos, width=2, alpha=0.7, edge_color=EDGE_COLORS.get("depends_on"), arrows=True, arrowsize=15) # Draw labels with just the component name (without the "component:" prefix) labels = {node: G.nodes[node].get("name", "") for node in DG.nodes} nx.draw_networkx_labels(DG, pos, labels=labels, font_size=10, font_family="sans-serif") plt.axis("off") plt.title("Component Dependencies") plt.tight_layout() plt.savefig(output_file, dpi=300, bbox_inches="tight") plt.close() print(f"Component dependencies visualization saved to {output_file}") def visualize_error_solutions(G, output_file): """Visualize errors and their solutions.""" # Create a subgraph with only error and solution nodes error_nodes = [node for node in G.nodes if G.nodes[node].get("type") == "error"] solution_nodes = [node for node in G.nodes if G.nodes[node].get("type") == "solution"] # Also include components that cause errors component_nodes = [] for error in error_nodes: for u, v in G.in_edges(error): if G.nodes[u].get("type") == "component": component_nodes.append(u) nodes = error_nodes + solution_nodes + component_nodes SG = G.subgraph(nodes) plt.figure(figsize=(15, 15)) # Set node colors based on type node_colors = [NODE_COLORS.get(SG.nodes[node].get("type"), "#9E9E9E") for node in SG.nodes] # Set edge colors based on type edge_colors = [EDGE_COLORS.get(SG.edges[edge].get("type"), "#9E9E9E") for edge in SG.edges] # Create layout pos = nx.spring_layout(SG, k=0.3, iterations=50) # Draw nodes nx.draw_networkx_nodes(SG, pos, node_size=400, node_color=node_colors, alpha=0.8) # Draw edges nx.draw_networkx_edges(SG, pos, width=1.5, alpha=0.7, edge_color=edge_colors, arrows=True, arrowsize=12) # Draw labels labels = {node: SG.nodes[node].get("name", "").split(":")[0] for node in SG.nodes} nx.draw_networkx_labels(SG, pos, labels=labels, font_size=9, font_family="sans-serif") # Create legend for node types node_patches = [mpatches.Patch(color=NODE_COLORS.get(t), label=t) for t in ["component", "error", "solution"]] plt.legend(handles=node_patches, title="Node Types", loc="upper left", bbox_to_anchor=(1, 1)) plt.axis("off") plt.title("Errors and Solutions") plt.tight_layout() plt.savefig(output_file, dpi=300, bbox_inches="tight") plt.close() print(f"Error-solution visualization saved to {output_file}") def main(): parser = argparse.ArgumentParser(description="Visualize the knowledge graph") parser.add_argument("--input", help="Input graph file", default=str(GRAPH_FILE)) parser.add_argument("--output-dir", help="Output directory", default=str(OUTPUT_DIR)) args = parser.parse_args() graph_file = Path(args.input) output_dir = Path(args.output_dir) # Create output directory if it doesn't exist output_dir.mkdir(parents=True, exist_ok=True) # Load knowledge graph knowledge_graph = load_knowledge_graph(graph_file) if not knowledge_graph: print("Failed to load knowledge graph.") return # Create NetworkX graph G = create_graph(knowledge_graph) # Generate visualizations visualize_full_graph(G, output_dir / "full_graph.png") visualize_component_dependencies(G, output_dir / "component_dependencies.png") visualize_error_solutions(G, output_dir / "error_solutions.png") print("All visualizations generated successfully.") if __name__ == "__main__": main()

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/0xjcf/MCP_CodeAnalysis'

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