Skip to main content
Glama
reporting.py53.1 kB
"""Reporting and visualization for Ultimate MCP Server analytics.""" import json import os from datetime import datetime from pathlib import Path from typing import Any, Dict, List, Optional, Union from ultimate_mcp_server.services.analytics.metrics import get_metrics_tracker from ultimate_mcp_server.utils import get_logger logger = get_logger(__name__) try: import matplotlib.dates as mdates import matplotlib.pyplot as plt import pandas as pd PLOTTING_AVAILABLE = True except ImportError: PLOTTING_AVAILABLE = False class AnalyticsReporting: """Provides comprehensive reporting and visualization capabilities for Ultimate MCP Server analytics. This class offers tools to generate detailed usage, cost, and provider-specific reports in various formats (JSON, HTML, Markdown) with optional data visualizations. It serves as the primary interface for extracting actionable insights from the server's operational metrics and presenting them in human-readable formats. Features: - Multiple report types: usage reports, provider-specific analysis, and cost breakdowns - Multiple output formats: JSON, HTML, and Markdown - Optional data visualizations using matplotlib (when available) - Customizable reporting periods - Persistent report storage The reporting system uses the metrics tracked by the MetricsTracker to generate these reports, providing insights into token usage, costs, request patterns, cache efficiency, and provider/model distribution. Usage: # Create a reporting instance reporter = AnalyticsReporting() # Generate a usage report for the last 7 days report_path = reporter.generate_usage_report(days=7, output_format="html") # Generate a cost analysis report for the last month cost_report = reporter.generate_cost_report(days=30, output_format="json") # Generate a provider-specific report provider_report = reporter.generate_provider_report( provider="anthropic", days=14, output_format="markdown" ) """ def __init__( self, reports_dir: Optional[Union[str, Path]] = None, include_plots: bool = True ): """Initialize the analytics reporting. Args: reports_dir: Directory for reports storage include_plots: Whether to include plots in reports """ # Set reports directory if reports_dir: self.reports_dir = Path(reports_dir) else: self.reports_dir = Path.home() / ".ultimate" / "reports" # Create reports directory if it doesn't exist self.reports_dir.mkdir(parents=True, exist_ok=True) # Plotting settings self.include_plots = include_plots and PLOTTING_AVAILABLE # Get metrics tracker self.metrics = get_metrics_tracker() logger.info( f"Analytics reporting initialized (dir: {self.reports_dir}, plots: {self.include_plots})", emoji_key="analytics" ) def generate_usage_report( self, days: int = 7, output_format: str = "json", include_plots: Optional[bool] = None ) -> Union[Dict[str, Any], str, Path]: """Generate a usage report. Args: days: Number of days to include in the report output_format: Output format (json, html, markdown) include_plots: Whether to include plots (overrides default setting) Returns: Report data or path to report file """ # Get metrics metrics = self.metrics.get_stats() # Determine plotting do_plots = self.include_plots if include_plots is None else include_plots do_plots = do_plots and PLOTTING_AVAILABLE # Build report data report_data = { "generated_at": datetime.now().isoformat(), "period": f"{days} days", "general": metrics["general"], "cache": metrics["cache"], "top_providers": metrics["top_providers"], "top_models": metrics["top_models"], "daily_usage": [ day for day in metrics["daily_usage"] if (datetime.now() - datetime.strptime(day["date"], "%Y-%m-%d")).days < days ], } # Generate report based on format if output_format == "json": # JSON format report_path = self.reports_dir / f"usage_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" with open(report_path, "w") as f: json.dump(report_data, f, indent=2) logger.info( f"Generated JSON usage report: {report_path}", emoji_key="analytics" ) return report_path elif output_format == "html": # HTML format (with optional plots) report_path = self.reports_dir / f"usage_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.html" # Generate plots if requested plot_paths = [] if do_plots: plot_paths = self._generate_report_plots(report_data, days) # Generate HTML html = self._generate_html_report(report_data, plot_paths) with open(report_path, "w") as f: f.write(html) logger.info( f"Generated HTML usage report: {report_path}", emoji_key="analytics" ) return report_path elif output_format == "markdown": # Markdown format report_path = self.reports_dir / f"usage_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md" # Generate plots if requested plot_paths = [] if do_plots: plot_paths = self._generate_report_plots(report_data, days) # Generate Markdown markdown = self._generate_markdown_report(report_data, plot_paths) with open(report_path, "w") as f: f.write(markdown) logger.info( f"Generated Markdown usage report: {report_path}", emoji_key="analytics" ) return report_path else: # Default to raw data logger.warning( f"Unknown output format: {output_format}, returning raw data", emoji_key="warning" ) return report_data def generate_provider_report( self, provider: str, days: int = 7, output_format: str = "json", include_plots: Optional[bool] = None ) -> Union[Dict[str, Any], str, Path]: """Generate a provider-specific report. Args: provider: Provider name days: Number of days to include in the report output_format: Output format (json, html, markdown) include_plots: Whether to include plots (overrides default setting) Returns: Report data or path to report file """ # Get metrics metrics = self.metrics.get_stats() # Check if provider exists if provider not in metrics["providers"]: logger.error( f"Unknown provider: {provider}", emoji_key="error" ) return {"error": f"Unknown provider: {provider}"} # Determine plotting do_plots = self.include_plots if include_plots is None else include_plots do_plots = do_plots and PLOTTING_AVAILABLE # Extract provider-specific data provider_data = metrics["providers"][provider] provider_models = { model: data for model, data in metrics["models"].items() if model.startswith(provider) or model.lower().startswith(provider.lower()) } # Collect daily usage for this provider (approximate) provider_share = provider_data["tokens"] / metrics["general"]["tokens_total"] if metrics["general"]["tokens_total"] > 0 else 0 provider_daily = [ { "date": day["date"], "tokens": int(day["tokens"] * provider_share), # Approximate "cost": day["cost"] * provider_share, # Approximate } for day in metrics["daily_usage"] if (datetime.now() - datetime.strptime(day["date"], "%Y-%m-%d")).days < days ] # Build report data report_data = { "generated_at": datetime.now().isoformat(), "period": f"{days} days", "provider": provider, "stats": provider_data, "models": provider_models, "daily_usage": provider_daily, "percentage_of_total": provider_share * 100, } # Generate report based on format if output_format == "json": # JSON format report_path = self.reports_dir / f"{provider}_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" with open(report_path, "w") as f: json.dump(report_data, f, indent=2) logger.info( f"Generated JSON provider report: {report_path}", emoji_key="analytics" ) return report_path elif output_format == "html": # HTML format (with optional plots) report_path = self.reports_dir / f"{provider}_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.html" # Generate plots if requested plot_paths = [] if do_plots: plot_paths = self._generate_provider_plots(report_data, provider, days) # Generate HTML html = self._generate_html_provider_report(report_data, plot_paths) with open(report_path, "w") as f: f.write(html) logger.info( f"Generated HTML provider report: {report_path}", emoji_key="analytics" ) return report_path elif output_format == "markdown": # Markdown format report_path = self.reports_dir / f"{provider}_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md" # Generate plots if requested plot_paths = [] if do_plots: plot_paths = self._generate_provider_plots(report_data, provider, days) # Generate Markdown markdown = self._generate_markdown_provider_report(report_data, plot_paths) with open(report_path, "w") as f: f.write(markdown) logger.info( f"Generated Markdown provider report: {report_path}", emoji_key="analytics" ) return report_path else: # Default to raw data logger.warning( f"Unknown output format: {output_format}, returning raw data", emoji_key="warning" ) return report_data def generate_cost_report( self, days: int = 30, output_format: str = "json", include_plots: Optional[bool] = None ) -> Union[Dict[str, Any], str, Path]: """Generate a cost analysis report. Args: days: Number of days to include in the report output_format: Output format (json, html, markdown) include_plots: Whether to include plots (overrides default setting) Returns: Report data or path to report file """ # Get metrics metrics = self.metrics.get_stats() # Determine plotting do_plots = self.include_plots if include_plots is None else include_plots do_plots = do_plots and PLOTTING_AVAILABLE # Process daily cost data daily_costs = [ { "date": day["date"], "cost": day["cost"], } for day in metrics["daily_usage"] if (datetime.now() - datetime.strptime(day["date"], "%Y-%m-%d")).days < days ] # Calculate cost by provider provider_costs = [ { "provider": provider, "cost": data["cost"], "percentage": data["cost"] / metrics["general"]["cost_total"] * 100 if metrics["general"]["cost_total"] > 0 else 0, } for provider, data in metrics["providers"].items() ] provider_costs.sort(key=lambda x: x["cost"], reverse=True) # Calculate cost by model model_costs = [ { "model": model, "cost": data["cost"], "percentage": data["cost"] / metrics["general"]["cost_total"] * 100 if metrics["general"]["cost_total"] > 0 else 0, } for model, data in metrics["models"].items() ] model_costs.sort(key=lambda x: x["cost"], reverse=True) # Calculate cost efficiency (tokens per dollar) cost_efficiency = [ { "model": model, "tokens_per_dollar": data["tokens"] / data["cost"] if data["cost"] > 0 else 0, "tokens": data["tokens"], "cost": data["cost"], } for model, data in metrics["models"].items() if data["cost"] > 0 ] cost_efficiency.sort(key=lambda x: x["tokens_per_dollar"], reverse=True) # Build report data report_data = { "generated_at": datetime.now().isoformat(), "period": f"{days} days", "total_cost": metrics["general"]["cost_total"], "cache_savings": metrics["cache"]["saved_cost"], "daily_costs": daily_costs, "provider_costs": provider_costs, "model_costs": model_costs, "cost_efficiency": cost_efficiency, } # Generate report based on format if output_format == "json": # JSON format report_path = self.reports_dir / f"cost_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" with open(report_path, "w") as f: json.dump(report_data, f, indent=2) logger.info( f"Generated JSON cost report: {report_path}", emoji_key="analytics" ) return report_path elif output_format == "html": # HTML format (with optional plots) report_path = self.reports_dir / f"cost_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.html" # Generate plots if requested plot_paths = [] if do_plots: plot_paths = self._generate_cost_plots(report_data, days) # Generate HTML html = self._generate_html_cost_report(report_data, plot_paths) with open(report_path, "w") as f: f.write(html) logger.info( f"Generated HTML cost report: {report_path}", emoji_key="analytics" ) return report_path elif output_format == "markdown": # Markdown format report_path = self.reports_dir / f"cost_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md" # Generate plots if requested plot_paths = [] if do_plots: plot_paths = self._generate_cost_plots(report_data, days) # Generate Markdown markdown = self._generate_markdown_cost_report(report_data, plot_paths) with open(report_path, "w") as f: f.write(markdown) logger.info( f"Generated Markdown cost report: {report_path}", emoji_key="analytics" ) return report_path else: # Default to raw data logger.warning( f"Unknown output format: {output_format}, returning raw data", emoji_key="warning" ) return report_data def _generate_report_plots( self, report_data: Dict[str, Any], days: int ) -> List[str]: """Generate plots for a usage report. Args: report_data: Report data days: Number of days to include Returns: List of plot file paths """ if not PLOTTING_AVAILABLE: return [] plot_paths = [] # Create daily usage plot if report_data["daily_usage"]: try: # Prepare data df = pd.DataFrame(report_data["daily_usage"]) df["date"] = pd.to_datetime(df["date"]) df = df.sort_values("date") # Create plot directory plot_dir = self.reports_dir / "plots" plot_dir.mkdir(exist_ok=True) # Create plot plt.figure(figsize=(10, 6)) plt.plot(df["date"], df["tokens"], marker="o", linestyle="-", linewidth=2) plt.title(f"Daily Token Usage (Last {days} Days)") plt.xlabel("Date") plt.ylabel("Tokens") plt.grid(True, alpha=0.3) plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d")) plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=max(1, days // 7))) plt.xticks(rotation=45) plt.tight_layout() # Save plot plot_path = str(plot_dir / f"daily_usage_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png") plt.savefig(plot_path) plt.close() plot_paths.append(plot_path) except Exception as e: logger.error( f"Failed to generate daily usage plot: {str(e)}", emoji_key="error" ) # Create provider distribution plot if report_data["top_providers"]: try: # Prepare data providers = [p["provider"] for p in report_data["top_providers"]] percentages = [p["percentage"] * 100 for p in report_data["top_providers"]] # Create plot plt.figure(figsize=(8, 8)) plt.pie(percentages, labels=providers, autopct="%1.1f%%", startangle=90, shadow=True) plt.axis("equal") plt.title("Token Usage by Provider") plt.tight_layout() # Save plot plot_path = str(plot_dir / f"provider_distribution_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png") plt.savefig(plot_path) plt.close() plot_paths.append(plot_path) except Exception as e: logger.error( f"Failed to generate provider distribution plot: {str(e)}", emoji_key="error" ) # Create model distribution plot if report_data["top_models"]: try: # Prepare data models = [m["model"] for m in report_data["top_models"]] percentages = [m["percentage"] * 100 for m in report_data["top_models"]] # Create plot plt.figure(figsize=(10, 6)) plt.bar(models, percentages) plt.title("Token Usage by Model") plt.xlabel("Model") plt.ylabel("Percentage of Total Tokens") plt.xticks(rotation=45, ha="right") plt.grid(True, alpha=0.3, axis="y") plt.tight_layout() # Save plot plot_path = str(plot_dir / f"model_distribution_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png") plt.savefig(plot_path) plt.close() plot_paths.append(plot_path) except Exception as e: logger.error( f"Failed to generate model distribution plot: {str(e)}", emoji_key="error" ) return plot_paths def _generate_provider_plots( self, report_data: Dict[str, Any], provider: str, days: int ) -> List[str]: """Generate plots for a provider report. Args: report_data: Report data provider: Provider name days: Number of days to include Returns: List of plot file paths """ if not PLOTTING_AVAILABLE: return [] plot_paths = [] # Create plot directory plot_dir = self.reports_dir / "plots" plot_dir.mkdir(exist_ok=True) # Create daily usage plot if report_data["daily_usage"]: try: # Prepare data df = pd.DataFrame(report_data["daily_usage"]) df["date"] = pd.to_datetime(df["date"]) df = df.sort_values("date") # Create plot plt.figure(figsize=(10, 6)) plt.plot(df["date"], df["tokens"], marker="o", linestyle="-", linewidth=2) plt.title(f"{provider} Daily Token Usage (Last {days} Days)") plt.xlabel("Date") plt.ylabel("Tokens") plt.grid(True, alpha=0.3) plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d")) plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=max(1, days // 7))) plt.xticks(rotation=45) plt.tight_layout() # Save plot plot_path = str(plot_dir / f"{provider}_daily_usage_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png") plt.savefig(plot_path) plt.close() plot_paths.append(plot_path) except Exception as e: logger.error( f"Failed to generate provider daily usage plot: {str(e)}", emoji_key="error" ) # Create model distribution plot if report_data["models"]: try: # Prepare data models = list(report_data["models"].keys()) tokens = [data["tokens"] for _, data in report_data["models"].items()] # Create plot plt.figure(figsize=(10, 6)) plt.bar(models, tokens) plt.title(f"{provider} Token Usage by Model") plt.xlabel("Model") plt.ylabel("Tokens") plt.xticks(rotation=45, ha="right") plt.grid(True, alpha=0.3, axis="y") plt.tight_layout() # Save plot plot_path = str(plot_dir / f"{provider}_model_distribution_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png") plt.savefig(plot_path) plt.close() plot_paths.append(plot_path) except Exception as e: logger.error( f"Failed to generate provider model distribution plot: {str(e)}", emoji_key="error" ) return plot_paths def _generate_cost_plots( self, report_data: Dict[str, Any], days: int ) -> List[str]: """Generate plots for a cost report. Args: report_data: Report data days: Number of days to include Returns: List of plot file paths """ if not PLOTTING_AVAILABLE: return [] plot_paths = [] # Create plot directory plot_dir = self.reports_dir / "plots" plot_dir.mkdir(exist_ok=True) # Create daily cost plot if report_data["daily_costs"]: try: # Prepare data df = pd.DataFrame(report_data["daily_costs"]) df["date"] = pd.to_datetime(df["date"]) df = df.sort_values("date") # Create plot plt.figure(figsize=(10, 6)) plt.plot(df["date"], df["cost"], marker="o", linestyle="-", linewidth=2) plt.title(f"Daily Cost (Last {days} Days)") plt.xlabel("Date") plt.ylabel("Cost ($)") plt.grid(True, alpha=0.3) plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d")) plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=max(1, days // 7))) plt.xticks(rotation=45) plt.tight_layout() # Save plot plot_path = str(plot_dir / f"daily_cost_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png") plt.savefig(plot_path) plt.close() plot_paths.append(plot_path) except Exception as e: logger.error( f"Failed to generate daily cost plot: {str(e)}", emoji_key="error" ) # Create provider cost distribution plot if report_data["provider_costs"]: try: # Prepare data providers = [p["provider"] for p in report_data["provider_costs"]] costs = [p["cost"] for p in report_data["provider_costs"]] # Create plot plt.figure(figsize=(8, 8)) plt.pie(costs, labels=providers, autopct="%1.1f%%", startangle=90, shadow=True) plt.axis("equal") plt.title("Cost by Provider") plt.tight_layout() # Save plot plot_path = str(plot_dir / f"provider_cost_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png") plt.savefig(plot_path) plt.close() plot_paths.append(plot_path) except Exception as e: logger.error( f"Failed to generate provider cost distribution plot: {str(e)}", emoji_key="error" ) # Create cost efficiency plot if report_data["cost_efficiency"]: try: # Prepare data (limit to top 10 for readability) top_efficient = report_data["cost_efficiency"][:10] models = [m["model"] for m in top_efficient] efficiency = [m["tokens_per_dollar"] for m in top_efficient] # Create plot plt.figure(figsize=(10, 6)) plt.bar(models, efficiency) plt.title("Cost Efficiency (Tokens per Dollar)") plt.xlabel("Model") plt.ylabel("Tokens per Dollar") plt.xticks(rotation=45, ha="right") plt.grid(True, alpha=0.3, axis="y") plt.tight_layout() # Save plot plot_path = str(plot_dir / f"cost_efficiency_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png") plt.savefig(plot_path) plt.close() plot_paths.append(plot_path) except Exception as e: logger.error( f"Failed to generate cost efficiency plot: {str(e)}", emoji_key="error" ) return plot_paths def _generate_html_report(self, report_data: Dict[str, Any], plot_paths: List[str]) -> str: """Generate an HTML usage report. Args: report_data: Report data plot_paths: List of plot file paths Returns: HTML report content """ # Basic HTML template html = f"""<!DOCTYPE html> <html> <head> <title>Ultimate MCP Server Usage Report</title> <style> body {{ font-family: Arial, sans-serif; margin: 20px; }} h1, h2, h3 {{ color: #333; }} .container {{ max-width: 1200px; margin: 0 auto; }} .card {{ background: #f9f9f9; border-radius: 5px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }} table {{ width: 100%; border-collapse: collapse; }} th, td {{ padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }} th {{ background-color: #f2f2f2; }} .stat {{ font-size: 24px; font-weight: bold; color: #0066cc; }} .plot {{ max-width: 100%; height: auto; margin: 20px 0; }} </style> </head> <body> <div class="container"> <h1>Ultimate MCP Server Usage Report</h1> <p>Generated at: {report_data["generated_at"]}</p> <p>Period: {report_data["period"]}</p> <div class="card"> <h2>General Statistics</h2> <table> <tr> <td>Uptime</td> <td class="stat">{report_data["general"]["uptime_human"]}</td> </tr> <tr> <td>Total Requests</td> <td class="stat">{report_data["general"]["requests_total"]:,}</td> </tr> <tr> <td>Total Tokens</td> <td class="stat">{report_data["general"]["tokens_total"]:,}</td> </tr> <tr> <td>Total Cost</td> <td class="stat">${report_data["general"]["cost_total"]:.2f}</td> </tr> <tr> <td>Average Response Time</td> <td class="stat">{report_data["general"]["avg_response_time"]:.3f}s</td> </tr> <tr> <td>Total Errors</td> <td class="stat">{report_data["general"]["errors_total"]}</td> </tr> <tr> <td>Error Rate</td> <td class="stat">{report_data["general"]["error_rate"]*100:.2f}%</td> </tr> </table> </div> <div class="card"> <h2>Cache Statistics</h2> <table> <tr> <td>Cache Hits</td> <td class="stat">{report_data["cache"]["hits"]:,}</td> </tr> <tr> <td>Cache Misses</td> <td class="stat">{report_data["cache"]["misses"]:,}</td> </tr> <tr> <td>Hit Ratio</td> <td class="stat">{report_data["cache"]["hit_ratio"]*100:.2f}%</td> </tr> <tr> <td>Cost Savings</td> <td class="stat">${report_data["cache"]["saved_cost"]:.2f}</td> </tr> </table> </div> """ # Add plots if available if plot_paths: html += """ <div class="card"> <h2>Usage Visualizations</h2> """ for plot_path in plot_paths: # Use relative path rel_path = os.path.relpath(plot_path, self.reports_dir) html += f""" <img class="plot" src="{rel_path}" alt="Usage Plot"> """ html += """ </div> """ # Add top providers if report_data["top_providers"]: html += """ <div class="card"> <h2>Top Providers</h2> <table> <tr> <th>Provider</th> <th>Tokens</th> <th>Percentage</th> </tr> """ for provider in report_data["top_providers"]: html += f""" <tr> <td>{provider["provider"]}</td> <td>{provider["tokens"]:,}</td> <td>{provider["percentage"]*100:.2f}%</td> </tr> """ html += """ </table> </div> """ # Add top models if report_data["top_models"]: html += """ <div class="card"> <h2>Top Models</h2> <table> <tr> <th>Model</th> <th>Tokens</th> <th>Percentage</th> </tr> """ for model in report_data["top_models"]: html += f""" <tr> <td>{model["model"]}</td> <td>{model["tokens"]:,}</td> <td>{model["percentage"]*100:.2f}%</td> </tr> """ html += """ </table> </div> """ # Add daily usage if report_data["daily_usage"]: html += """ <div class="card"> <h2>Daily Usage</h2> <table> <tr> <th>Date</th> <th>Tokens</th> <th>Cost</th> </tr> """ for day in sorted(report_data["daily_usage"], key=lambda x: x["date"], reverse=True): html += f""" <tr> <td>{day["date"]}</td> <td>{day["tokens"]:,}</td> <td>${day["cost"]:.2f}</td> </tr> """ html += """ </table> </div> """ # Close HTML html += """ </div> </body> </html> """ return html def _generate_markdown_report(self, report_data: Dict[str, Any], plot_paths: List[str]) -> str: """Generate a Markdown usage report. Args: report_data: Report data plot_paths: List of plot file paths Returns: Markdown report content """ # Basic Markdown template markdown = f"""# Ultimate MCP Server Usage Report Generated at: {report_data["generated_at"]} Period: {report_data["period"]} ## General Statistics - **Uptime:** {report_data["general"]["uptime_human"]} - **Total Requests:** {report_data["general"]["requests_total"]:,} - **Total Tokens:** {report_data["general"]["tokens_total"]:,} - **Total Cost:** ${report_data["general"]["cost_total"]:.2f} - **Average Response Time:** {report_data["general"]["avg_response_time"]:.3f}s - **Total Errors:** {report_data["general"]["errors_total"]} - **Error Rate:** {report_data["general"]["error_rate"]*100:.2f}% ## Cache Statistics - **Cache Hits:** {report_data["cache"]["hits"]:,} - **Cache Misses:** {report_data["cache"]["misses"]:,} - **Hit Ratio:** {report_data["cache"]["hit_ratio"]*100:.2f}% - **Cost Savings:** ${report_data["cache"]["saved_cost"]:.2f} """ # Add plots if available if plot_paths: markdown += """## Usage Visualizations """ for plot_path in plot_paths: # Use relative path rel_path = os.path.relpath(plot_path, self.reports_dir) markdown += f"""![Usage Plot]({rel_path}) """ # Add top providers if report_data["top_providers"]: markdown += """## Top Providers | Provider | Tokens | Percentage | |----------|--------|------------| """ for provider in report_data["top_providers"]: markdown += f"""| {provider["provider"]} | {provider["tokens"]:,} | {provider["percentage"]*100:.2f}% | """ markdown += "\n" # Add top models if report_data["top_models"]: markdown += """## Top Models | Model | Tokens | Percentage | |-------|--------|------------| """ for model in report_data["top_models"]: markdown += f"""| {model["model"]} | {model["tokens"]:,} | {model["percentage"]*100:.2f}% | """ markdown += "\n" # Add daily usage if report_data["daily_usage"]: markdown += """## Daily Usage | Date | Tokens | Cost | |------|--------|------| """ for day in sorted(report_data["daily_usage"], key=lambda x: x["date"], reverse=True): markdown += f"""| {day["date"]} | {day["tokens"]:,} | ${day["cost"]:.2f} | """ return markdown def _generate_html_provider_report(self, report_data: Dict[str, Any], plot_paths: List[str]) -> str: """Generate an HTML provider report. Args: report_data: Report data plot_paths: List of plot file paths Returns: HTML report content """ # Basic HTML template (similar to usage report but provider-specific) provider = report_data["provider"] provider_stats = report_data["stats"] html = f"""<!DOCTYPE html> <html> <head> <title>{provider} Provider Report</title> <style> body {{ font-family: Arial, sans-serif; margin: 20px; }} h1, h2, h3 {{ color: #333; }} .container {{ max-width: 1200px; margin: 0 auto; }} .card {{ background: #f9f9f9; border-radius: 5px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }} table {{ width: 100%; border-collapse: collapse; }} th, td {{ padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }} th {{ background-color: #f2f2f2; }} .stat {{ font-size: 24px; font-weight: bold; color: #0066cc; }} .plot {{ max-width: 100%; height: auto; margin: 20px 0; }} </style> </head> <body> <div class="container"> <h1>{provider} Provider Report</h1> <p>Generated at: {report_data["generated_at"]}</p> <p>Period: {report_data["period"]}</p> <div class="card"> <h2>Provider Statistics</h2> <table> <tr> <td>Total Requests</td> <td class="stat">{provider_stats["requests"]:,}</td> </tr> <tr> <td>Total Tokens</td> <td class="stat">{provider_stats["tokens"]:,}</td> </tr> <tr> <td>Total Cost</td> <td class="stat">${provider_stats["cost"]:.2f}</td> </tr> <tr> <td>Average Response Time</td> <td class="stat">{provider_stats["avg_response_time"]:.3f}s</td> </tr> <tr> <td>Total Errors</td> <td class="stat">{provider_stats["errors"]}</td> </tr> <tr> <td>Percentage of Total Usage</td> <td class="stat">{report_data["percentage_of_total"]:.2f}%</td> </tr> </table> </div> """ # Add plots if available if plot_paths: html += """ <div class="card"> <h2>Usage Visualizations</h2> """ for plot_path in plot_paths: # Use relative path rel_path = os.path.relpath(plot_path, self.reports_dir) html += f""" <img class="plot" src="{rel_path}" alt="Provider Usage Plot"> """ html += """ </div> """ # Add models if report_data["models"]: html += """ <div class="card"> <h2>Models</h2> <table> <tr> <th>Model</th> <th>Requests</th> <th>Tokens</th> <th>Cost</th> <th>Avg Response Time</th> </tr> """ for model, data in report_data["models"].items(): html += f""" <tr> <td>{model}</td> <td>{data["requests"]:,}</td> <td>{data["tokens"]:,}</td> <td>${data["cost"]:.2f}</td> <td>{data["avg_response_time"]:.3f}s</td> </tr> """ html += """ </table> </div> """ # Add daily usage if report_data["daily_usage"]: html += """ <div class="card"> <h2>Daily Usage</h2> <table> <tr> <th>Date</th> <th>Tokens</th> <th>Cost</th> </tr> """ for day in sorted(report_data["daily_usage"], key=lambda x: x["date"], reverse=True): html += f""" <tr> <td>{day["date"]}</td> <td>{day["tokens"]:,}</td> <td>${day["cost"]:.2f}</td> </tr> """ html += """ </table> </div> """ # Close HTML html += """ </div> </body> </html> """ return html def _generate_markdown_provider_report(self, report_data: Dict[str, Any], plot_paths: List[str]) -> str: """Generate a Markdown provider report. Args: report_data: Report data plot_paths: List of plot file paths Returns: Markdown report content """ # Basic Markdown template (similar to usage report but provider-specific) provider = report_data["provider"] provider_stats = report_data["stats"] markdown = f"""# {provider} Provider Report Generated at: {report_data["generated_at"]} Period: {report_data["period"]} ## Provider Statistics - **Total Requests:** {provider_stats["requests"]:,} - **Total Tokens:** {provider_stats["tokens"]:,} - **Total Cost:** ${provider_stats["cost"]:.2f} - **Average Response Time:** {provider_stats["avg_response_time"]:.3f}s - **Total Errors:** {provider_stats["errors"]} - **Percentage of Total Usage:** {report_data["percentage_of_total"]:.2f}% """ # Add plots if available if plot_paths: markdown += """## Usage Visualizations """ for plot_path in plot_paths: # Use relative path rel_path = os.path.relpath(plot_path, self.reports_dir) markdown += f"""![Provider Usage Plot]({rel_path}) """ # Add models if report_data["models"]: markdown += """## Models | Model | Requests | Tokens | Cost | Avg Response Time | |-------|----------|--------|------|-------------------| """ for model, data in report_data["models"].items(): markdown += f"""| {model} | {data["requests"]:,} | {data["tokens"]:,} | ${data["cost"]:.2f} | {data["avg_response_time"]:.3f}s | """ markdown += "\n" # Add daily usage if report_data["daily_usage"]: markdown += """## Daily Usage | Date | Tokens | Cost | |------|--------|------| """ for day in sorted(report_data["daily_usage"], key=lambda x: x["date"], reverse=True): markdown += f"""| {day["date"]} | {day["tokens"]:,} | ${day["cost"]:.2f} | """ return markdown def _generate_html_cost_report(self, report_data: Dict[str, Any], plot_paths: List[str]) -> str: """Generate an HTML cost report. Args: report_data: Report data plot_paths: List of plot file paths Returns: HTML report content """ # Basic HTML template (cost-focused) html = f"""<!DOCTYPE html> <html> <head> <title>Ultimate MCP Server Cost Report</title> <style> body {{ font-family: Arial, sans-serif; margin: 20px; }} h1, h2, h3 {{ color: #333; }} .container {{ max-width: 1200px; margin: 0 auto; }} .card {{ background: #f9f9f9; border-radius: 5px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }} table {{ width: 100%; border-collapse: collapse; }} th, td {{ padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }} th {{ background-color: #f2f2f2; }} .stat {{ font-size: 24px; font-weight: bold; color: #0066cc; }} .cost {{ font-size: 24px; font-weight: bold; color: #cc0000; }} .savings {{ font-size: 24px; font-weight: bold; color: #00cc00; }} .plot {{ max-width: 100%; height: auto; margin: 20px 0; }} </style> </head> <body> <div class="container"> <h1>Ultimate MCP Server Cost Report</h1> <p>Generated at: {report_data["generated_at"]}</p> <p>Period: {report_data["period"]}</p> <div class="card"> <h2>Cost Overview</h2> <table> <tr> <td>Total Cost</td> <td class="cost">${report_data["total_cost"]:.2f}</td> </tr> <tr> <td>Cache Savings</td> <td class="savings">${report_data["cache_savings"]:.2f}</td> </tr> <tr> <td>Net Cost</td> <td class="cost">${report_data["total_cost"] - report_data["cache_savings"]:.2f}</td> </tr> </table> </div> """ # Add plots if available if plot_paths: html += """ <div class="card"> <h2>Cost Visualizations</h2> """ for plot_path in plot_paths: # Use relative path rel_path = os.path.relpath(plot_path, self.reports_dir) html += f""" <img class="plot" src="{rel_path}" alt="Cost Plot"> """ html += """ </div> """ # Add provider costs if report_data["provider_costs"]: html += """ <div class="card"> <h2>Cost by Provider</h2> <table> <tr> <th>Provider</th> <th>Cost</th> <th>Percentage</th> </tr> """ for provider in report_data["provider_costs"]: html += f""" <tr> <td>{provider["provider"]}</td> <td>${provider["cost"]:.2f}</td> <td>{provider["percentage"]:.2f}%</td> </tr> """ html += """ </table> </div> """ # Add model costs if report_data["model_costs"]: html += """ <div class="card"> <h2>Cost by Model</h2> <table> <tr> <th>Model</th> <th>Cost</th> <th>Percentage</th> </tr> """ for model in report_data["model_costs"]: html += f""" <tr> <td>{model["model"]}</td> <td>${model["cost"]:.2f}</td> <td>{model["percentage"]:.2f}%</td> </tr> """ html += """ </table> </div> """ # Add cost efficiency if report_data["cost_efficiency"]: html += """ <div class="card"> <h2>Cost Efficiency (Tokens per Dollar)</h2> <table> <tr> <th>Model</th> <th>Tokens per Dollar</th> <th>Tokens</th> <th>Cost</th> </tr> """ for model in report_data["cost_efficiency"]: html += f""" <tr> <td>{model["model"]}</td> <td class="stat">{model["tokens_per_dollar"]:,.0f}</td> <td>{model["tokens"]:,}</td> <td>${model["cost"]:.2f}</td> </tr> """ html += """ </table> </div> """ # Add daily costs if report_data["daily_costs"]: html += """ <div class="card"> <h2>Daily Costs</h2> <table> <tr> <th>Date</th> <th>Cost</th> </tr> """ for day in sorted(report_data["daily_costs"], key=lambda x: x["date"], reverse=True): html += f""" <tr> <td>{day["date"]}</td> <td>${day["cost"]:.2f}</td> </tr> """ html += """ </table> </div> """ # Close HTML html += """ </div> </body> </html> """ return html def _generate_markdown_cost_report(self, report_data: Dict[str, Any], plot_paths: List[str]) -> str: """Generate a Markdown cost report. Args: report_data: Report data plot_paths: List of plot file paths Returns: Markdown report content """ # Basic Markdown template (cost-focused) markdown = f"""# Ultimate MCP Server Cost Report Generated at: {report_data["generated_at"]} Period: {report_data["period"]} ## Cost Overview - **Total Cost:** ${report_data["total_cost"]:.2f} - **Cache Savings:** ${report_data["cache_savings"]:.2f} - **Net Cost:** ${report_data["total_cost"] - report_data["cache_savings"]:.2f} """ # Add plots if available if plot_paths: markdown += """## Cost Visualizations """ for plot_path in plot_paths: # Use relative path rel_path = os.path.relpath(plot_path, self.reports_dir) markdown += f"""![Cost Plot]({rel_path}) """ # Add provider costs if report_data["provider_costs"]: markdown += """## Cost by Provider | Provider | Cost | Percentage | |----------|------|------------| """ for provider in report_data["provider_costs"]: markdown += f"""| {provider["provider"]} | ${provider["cost"]:.2f} | {provider["percentage"]:.2f}% | """ markdown += "\n" # Add model costs if report_data["model_costs"]: markdown += """## Cost by Model | Model | Cost | Percentage | |-------|------|------------| """ for model in report_data["model_costs"]: markdown += f"""| {model["model"]} | ${model["cost"]:.2f} | {model["percentage"]:.2f}% | """ markdown += "\n" # Add cost efficiency if report_data["cost_efficiency"]: markdown += """## Cost Efficiency (Tokens per Dollar) | Model | Tokens per Dollar | Tokens | Cost | |-------|-------------------|--------|------| """ for model in report_data["cost_efficiency"]: markdown += f"""| {model["model"]} | {model["tokens_per_dollar"]:,.0f} | {model["tokens"]:,} | ${model["cost"]:.2f} | """ markdown += "\n" # Add daily costs if report_data["daily_costs"]: markdown += """## Daily Costs | Date | Cost | |------|------| """ for day in sorted(report_data["daily_costs"], key=lambda x: x["date"], reverse=True): markdown += f"""| {day["date"]} | ${day["cost"]:.2f} | """ return markdown

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/Kappasig920/Ultimate-MCP-Server'

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