suggest_plot_templates
Analyzes your dataset characteristics and goals to recommend suitable plot templates for creating statistical visualizations with plotnine.
Instructions
Analyze data and suggest appropriate plot templates.
Examines data characteristics (number of numeric/categorical columns, presence of time data) and optionally a user goal to recommend suitable templates.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| data_source | Yes | Data source to analyze | |
| goal | No | Optional user goal (e.g., 'compare distributions', 'show trend', 'correlation') |
Implementation Reference
- src/plotnine_mcp/server.py:997-1072 (handler)Main handler function that processes tool arguments, loads and analyzes data structure, invokes suggest_template helper, and formats the response with recommended templates.async def suggest_plot_templates_handler(arguments: dict[str, Any]) -> list[TextContent]: """Handle suggest_plot_templates tool calls.""" try: data_source = DataSource(**arguments["data_source"]) goal = arguments.get("goal") # Load data to analyze try: data = load_data(data_source) except DataLoadError as e: return [ TextContent( type="text", text=f"Data loading error: {str(e)}\n\nCannot analyze data for suggestions.", ) ] # Analyze data characteristics import numpy as np numeric_cols = data.select_dtypes(include=[np.number]).columns categorical_cols = data.select_dtypes(include=["object", "category"]).columns # Check for datetime columns has_time = False for col in data.columns: if "date" in col.lower() or "time" in col.lower(): has_time = True break # Also check dtype if data[col].dtype == "datetime64[ns]": has_time = True break num_numeric = len(numeric_cols) num_categorical = len(categorical_cols) # Get suggestions suggestions = suggest_template(num_numeric, num_categorical, has_time, goal) # Format message message = "Template Suggestions\n" + "=" * 60 + "\n\n" message += f"Data characteristics:\n" message += f" • Numeric columns: {num_numeric} ({', '.join(numeric_cols) if num_numeric > 0 else 'none'})\n" message += f" • Categorical columns: {num_categorical} ({', '.join(categorical_cols) if num_categorical > 0 else 'none'})\n" message += f" • Time-based data: {'Yes' if has_time else 'No'}\n" if goal: message += f" • User goal: {goal}\n" message += "\n" if suggestions: message += f"Recommended templates ({len(suggestions)}):\n\n" all_templates = get_template_list() for i, template_name in enumerate(suggestions, 1): desc = all_templates.get(template_name, "") message += f"{i}. {template_name}\n" message += f" {desc}\n\n" else: message += "No specific templates recommended for this data.\n" message += "Try 'list_plot_templates' to see all available options.\n" message += "\n" + "=" * 60 + "\n" message += "Use 'create_plot_from_template' with one of these templates." return [TextContent(type="text", text=message)] except Exception as e: return [ TextContent( type="text", text=f"Error analyzing data: {str(e)}", ) ]
- src/plotnine_mcp/server.py:454-475 (registration)Tool registration in the list_tools() function, including name, description, and input schema definition.Tool( name="suggest_plot_templates", description="""Analyze data and suggest appropriate plot templates. Examines data characteristics (number of numeric/categorical columns, presence of time data) and optionally a user goal to recommend suitable templates.""", inputSchema={ "type": "object", "properties": { "data_source": { "type": "object", "description": "Data source to analyze", }, "goal": { "type": "string", "description": "Optional user goal (e.g., 'compare distributions', 'show trend', 'correlation')", }, }, "required": ["data_source"], }, ),
- src/plotnine_mcp/server.py:461-474 (schema)Input schema definition for the suggest_plot_templates tool, specifying data_source (required) and optional goal.inputSchema={ "type": "object", "properties": { "data_source": { "type": "object", "description": "Data source to analyze", }, "goal": { "type": "string", "description": "Optional user goal (e.g., 'compare distributions', 'show trend', 'correlation')", }, }, "required": ["data_source"], },
- Helper function containing the core logic for suggesting plot templates based on counts of numeric/categorical columns, presence of time data, and optional user goal.def suggest_template( num_numeric: int, num_categorical: int, has_time: bool, goal: Optional[str] = None ) -> list[str]: """ Suggest appropriate templates based on data characteristics. Args: num_numeric: Number of numeric columns num_categorical: Number of categorical columns has_time: Whether data has time/date columns goal: Optional user-specified goal (e.g., "compare", "trend", "distribution") Returns: List of suggested template names """ suggestions = [] # Time-based suggestions if has_time and num_numeric >= 1: suggestions.append("time_series") if num_categorical >= 1: suggestions.append("multi_line") # Distribution comparisons if num_categorical >= 1 and num_numeric >= 1: suggestions.append("distribution_comparison") suggestions.append("boxplot_comparison") # Correlation/relationship if num_numeric >= 2: suggestions.append("scatter_with_trend") if num_numeric >= 3: suggestions.append("correlation_heatmap") # Single variable distribution if num_numeric >= 1 and num_categorical == 0: suggestions.append("histogram_with_density") # Category breakdown if num_categorical >= 1: suggestions.append("category_breakdown") # Goal-based refinement if goal: goal_lower = goal.lower() if "trend" in goal_lower or "time" in goal_lower: suggestions = [s for s in suggestions if "time" in s or "line" in s] elif "compare" in goal_lower or "comparison" in goal_lower: suggestions = [ s for s in suggestions if "comparison" in s or "boxplot" in s ] elif "distribution" in goal_lower: suggestions = [ s for s in suggestions if "distribution" in s or "histogram" in s ] elif "correlation" in goal_lower or "relationship" in goal_lower: suggestions = [s for s in suggestions if "correlation" in s or "scatter" in s] # Remove duplicates while preserving order seen = set() unique_suggestions = [] for item in suggestions: if item not in seen: seen.add(item) unique_suggestions.append(item) return unique_suggestions[:5] # Return top 5