create_plot_from_template
Generate statistical plots using predefined templates for common visualization types like time series, scatter plots, and histograms, handling configuration automatically while allowing customization.
Instructions
Create a plot using a predefined template.
Templates provide optimized configurations for common plot types:
time_series: Line plot with date formatting
scatter_with_trend: Points with regression line
distribution_comparison: Violin + jitter for group comparison
category_breakdown: Bar chart with categories
correlation_heatmap: Tile plot for correlations
boxplot_comparison: Boxplot with points overlay
multi_line: Multiple lines for trend comparison
histogram_with_density: Histogram with density curve
before_after: Side-by-side comparison
You only need to provide data and aesthetics; the template handles the rest. You can override any template settings if needed.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| template_name | Yes | Name of the template to use | |
| data_source | Yes | Data source configuration | |
| aes | Yes | Aesthetic mappings (must include required aesthetics for template) | |
| labels | No | Optional plot labels (title, x, y, etc.) | |
| output | No | Optional output configuration | |
| overrides | No | Optional overrides for template config (geoms, theme, etc.) |
Implementation Reference
- src/plotnine_mcp/server.py:952-995 (handler)The handler function for the 'create_plot_from_template' tool. It extracts arguments, applies the template using apply_template from templates.py, calls the general create_plot_handler with the generated config, and prepends template information to the result message.async def create_plot_from_template_handler(arguments: dict[str, Any]) -> list[TextContent]: """Handle create_plot_from_template tool calls.""" try: template_name = arguments["template_name"] data_source = arguments["data_source"] aes = arguments["aes"] overrides = arguments.get("overrides", {}) # Apply labels and output if provided if "labels" in arguments: overrides["labels"] = arguments["labels"] if "output" in arguments: overrides["output"] = arguments["output"] # Apply template to create config try: config = apply_template(template_name, data_source, aes, overrides) except (KeyError, ValueError) as e: return [ TextContent( type="text", text=f"Template error: {str(e)}\n\nUse 'list_plot_templates' to see available templates.", ) ] # Create plot using the config result = await create_plot_handler(config) # Prepend template info original_message = result[0].text if result else "" new_message = f"""Plot created using template: {template_name} {original_message}""" return [TextContent(type="text", text=new_message)] except Exception as e: return [ TextContent( type="text", text=f"Error creating plot from template: {str(e)}\n\nPlease check your template name and aesthetics.", ) ]
- src/plotnine_mcp/server.py:423-452 (schema)The inputSchema defining the expected parameters for the tool: template_name (required), data_source, aes (required), labels, output, overrides.inputSchema={ "type": "object", "properties": { "template_name": { "type": "string", "description": "Name of the template to use", }, "data_source": { "type": "object", "description": "Data source configuration", }, "aes": { "type": "object", "description": "Aesthetic mappings (must include required aesthetics for template)", }, "labels": { "type": "object", "description": "Optional plot labels (title, x, y, etc.)", }, "output": { "type": "object", "description": "Optional output configuration", }, "overrides": { "type": "object", "description": "Optional overrides for template config (geoms, theme, etc.)", }, }, "required": ["template_name", "data_source", "aes"], },
- src/plotnine_mcp/server.py:406-453 (registration)The Tool object registration in the list_tools() function, including name, description of templates, and inputSchema.Tool( name="create_plot_from_template", description="""Create a plot using a predefined template. Templates provide optimized configurations for common plot types: - time_series: Line plot with date formatting - scatter_with_trend: Points with regression line - distribution_comparison: Violin + jitter for group comparison - category_breakdown: Bar chart with categories - correlation_heatmap: Tile plot for correlations - boxplot_comparison: Boxplot with points overlay - multi_line: Multiple lines for trend comparison - histogram_with_density: Histogram with density curve - before_after: Side-by-side comparison You only need to provide data and aesthetics; the template handles the rest. You can override any template settings if needed.""", inputSchema={ "type": "object", "properties": { "template_name": { "type": "string", "description": "Name of the template to use", }, "data_source": { "type": "object", "description": "Data source configuration", }, "aes": { "type": "object", "description": "Aesthetic mappings (must include required aesthetics for template)", }, "labels": { "type": "object", "description": "Optional plot labels (title, x, y, etc.)", }, "output": { "type": "object", "description": "Optional output configuration", }, "overrides": { "type": "object", "description": "Optional overrides for template config (geoms, theme, etc.)", }, }, "required": ["template_name", "data_source", "aes"], }, ),
- The apply_template function, which fetches the template config, validates required aesthetics, merges with provided data_source and aes, applies overrides, and returns full plot config for create_plot.def apply_template( template_name: str, data_source: dict[str, Any], aes: dict[str, str], overrides: Optional[dict[str, Any]] = None, ) -> dict[str, Any]: """ Apply a template to create a complete plot configuration. Args: template_name: Name of the template to use data_source: Data source configuration aes: Aesthetic mappings (must include required aesthetics) overrides: Optional overrides for template config Returns: Complete plot configuration ready for create_plot Raises: ValueError: If required aesthetics are missing KeyError: If template not found """ template = get_template(template_name) # Validate required aesthetics required = template["required_aesthetics"] provided = set(aes.keys()) missing = set(required) - provided if missing: raise ValueError( f"Template '{template_name}' requires aesthetics: {required}. " f"Missing: {list(missing)}" ) # Start with template config config = { "data_source": data_source, "aes": aes, **template["config"], } # Apply overrides if provided if overrides: config.update(overrides) return config
- src/plotnine_mcp/templates.py:8-130 (helper)The TEMPLATES dictionary defining all preset configurations for common plot types used by the tool.TEMPLATES = { "time_series": { "description": "Line plot optimized for time-based data with date formatting", "config": { "geoms": [{"type": "line", "params": {"size": 1}}], "scales": [{"aesthetic": "x", "type": "datetime", "params": {}}], "theme": { "base": "minimal", "customizations": {"figure_size": [12, 6]}, }, }, "required_aesthetics": ["x", "y"], "suggested_aesthetics": ["color", "group"], }, "scatter_with_trend": { "description": "Scatter plot with linear regression trend line and confidence interval", "config": { "geoms": [ {"type": "point", "params": {"size": 2, "alpha": 0.6}}, {"type": "smooth", "params": {"method": "lm", "se": True}}, ], "theme": {"base": "minimal"}, }, "required_aesthetics": ["x", "y"], "suggested_aesthetics": ["color"], }, "distribution_comparison": { "description": "Violin plot for comparing distributions across groups", "config": { "geoms": [ {"type": "violin", "params": {"alpha": 0.7}}, {"type": "jitter", "params": {"width": 0.1, "alpha": 0.3, "size": 1}}, ], "theme": {"base": "bw"}, }, "required_aesthetics": ["x", "y"], "suggested_aesthetics": ["fill", "color"], }, "category_breakdown": { "description": "Bar chart showing counts or values by category", "config": { "geoms": [{"type": "col", "params": {}}], "theme": { "base": "minimal", "customizations": {"legend_position": "bottom"}, }, "coords": {"type": "flip", "params": {}}, }, "required_aesthetics": ["x", "y"], "suggested_aesthetics": ["fill"], }, "correlation_heatmap": { "description": "Heatmap for visualizing correlations or relationships", "config": { "geoms": [{"type": "tile", "params": {}}], "scales": [ { "aesthetic": "fill", "type": "gradient", "params": {"low": "blue", "high": "red"}, } ], "theme": { "base": "minimal", "customizations": {"figure_size": [10, 8]}, }, }, "required_aesthetics": ["x", "y", "fill"], "suggested_aesthetics": [], }, "boxplot_comparison": { "description": "Boxplot with individual points for detailed distribution comparison", "config": { "geoms": [ {"type": "boxplot", "params": {"alpha": 0.7}}, {"type": "jitter", "params": {"width": 0.2, "alpha": 0.4, "size": 1}}, ], "theme": {"base": "bw"}, }, "required_aesthetics": ["x", "y"], "suggested_aesthetics": ["fill", "color"], }, "multi_line": { "description": "Multiple line plots for comparing trends across categories", "config": { "geoms": [{"type": "line", "params": {"size": 1.2}}], "theme": { "base": "minimal", "customizations": { "figure_size": [12, 6], "legend_position": "right", }, }, }, "required_aesthetics": ["x", "y", "color"], "suggested_aesthetics": ["linetype"], }, "histogram_with_density": { "description": "Histogram overlaid with kernel density curve", "config": { "geoms": [ {"type": "histogram", "params": {"alpha": 0.7, "bins": 30}}, {"type": "density", "params": {"alpha": 0}}, ], "theme": {"base": "minimal"}, }, "required_aesthetics": ["x"], "suggested_aesthetics": ["fill", "color"], }, "before_after": { "description": "Side-by-side comparison of before and after measurements", "config": { "geoms": [ {"type": "point", "params": {"size": 3}}, {"type": "line", "params": {"alpha": 0.5}}, ], "theme": {"base": "bw"}, "facets": {"type": "wrap", "params": {"ncol": 2}}, }, "required_aesthetics": ["x", "y"], "suggested_aesthetics": ["group", "color"], }, }