Skip to main content
Glama
mckinsey

vizro-mcp

Official
by mckinsey

validate_chart_code

Validate Python chart code for Plotly figures and optionally open visualization results in a browser to ensure proper functionality.

Instructions

Validate the chart code created by the user and optionally open the PyCafe link in a browser.

Returns:
    ValidationResults object with status and dashboard details

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
chart_configYesA ChartPlan object with the chart configuration
data_infoYesMetadata for the dataset to be used in the chart
auto_openNoWhether to automatically open the PyCafe link in a browser

Implementation Reference

  • The core handler function for the 'validate_chart_code' tool, registered via @mcp.tool() decorator. Validates ChartPlan input, generates executable Python code for the chart and a dashboard template, creates pycafe preview URL if data is remote, and optionally opens it in browser.
    @mcp.tool()
    def validate_chart_code(
        chart_config: ChartPlan = Field(description="A ChartPlan object with the chart configuration"),
        data_info: DFMetaData = Field(description="Metadata for the dataset to be used in the chart"),
        auto_open: bool = Field(default=True, description="Whether to automatically open the PyCafe link in a browser"),
    ) -> ValidateResults:
        """Validate the chart code created by the user and optionally open the PyCafe link in a browser.
    
        Returns:
            ValidationResults object with status and dashboard details
        """
        Vizro._reset()
    
        try:
            chart_plan_obj = ChartPlan.model_validate(chart_config)
        except ValidationError as e:
            return ValidateResults(
                valid=False,
                message=f"Validation Error: {e!s}",
                python_code="",
                pycafe_url=None,
                browser_opened=False,
            )
        else:
            dashboard_code = chart_plan_obj.get_dashboard_template(data_info=data_info)
    
            # Generate PyCafe URL if all data is remote
            pycafe_url = create_pycafe_url(dashboard_code) if data_info.file_location_type == "remote" else None
            browser_opened = False
    
            if auto_open and pycafe_url:
                try:
                    browser_opened = webbrowser.open(pycafe_url)
                except Exception:
                    browser_opened = False
    
            return ValidateResults(
                valid=True,
                message="Chart only dashboard created successfully!",
                python_code=chart_plan_obj.get_chart_code(vizro=True),
                pycafe_url=pycafe_url,
                browser_opened=browser_opened,
            )
    
        finally:
            Vizro._reset()
  • Dataclass defining the output schema returned by the validate_chart_code tool (and other validation tools), including validation status, message, generated Python code, pycafe URL, and browser open status.
    @dataclass
    class ValidateResults:
        """Results of validation tools."""
    
        valid: bool
        message: str
        python_code: str
        pycafe_url: str | None
        browser_opened: bool
  • Pydantic BaseModel ChartPlan defining the primary input schema for the validate_chart_code tool. Includes fields for chart_type, chart_name, imports, and chart_code with custom validator. Provides helper methods get_imports, get_chart_code, and get_dashboard_template used directly in the handler.
    class ChartPlan(BaseModel):
        """Base chart plan used to generate chart code based on user visualization requirements."""
    
        chart_type: str = Field(
            description="""
            Describes the chart type that best reflects the user request.
            """,
        )
        chart_name: str = Field(
            description="""
            The name of the chart function. Should be unique, concise and in snake_case.
            """,
            pattern=r"^[a-z][a-z0-9_]*$",
        )
        imports: list[str] = Field(
            description="""
            List of import statements required to render the chart defined by the `chart_code` field. Ensure that every
            import statement is a separate list/array entry: An example of valid list of import statements would be:
    
            ["import pandas as pd",
            "import plotly.express as px"]
            """,
        )
        chart_code: Annotated[
            str,
            AfterValidator(_check_chart_code),
            Field(
                description="""
            Python code that generates a generates a plotly go.Figure object. It must fulfill the following criteria:
            1. Must be wrapped in a function that is named `chart_name`
            2. Must accept as first argument argument `data_frame` which is a pandas DataFrame
            3. Must return a plotly go.Figure object
            4. All data used in the chart must be derived from the data_frame argument, all data manipulations
            must be done within the function.
            5. DO NOT modify the background (with plot_bgcolor) or color sequences unless explicitly asked for
            6. When creating hover templates, explicitly ensure that it works on light and dark mode
            """,
            ),
        ]
    
        _base_chart_imports: list[str] = PrivateAttr(BASE_IMPORTS)
    
        def get_imports(self, vizro: bool = False):
            imports = list(dict.fromkeys(self.imports + self._base_chart_imports))  # remove duplicates
            if vizro:
                imports = [imp for imp in imports if "import plotly.express as px" not in imp]
            else:
                imports = [imp for imp in imports if "vizro" not in imp]
            return "\n".join(imports) + "\n"
    
        def get_chart_code(self, chart_name: str | None = None, vizro: bool = False):
            chart_code = self.chart_code
            if vizro:
                chart_code = chart_code.replace(f"def {self.chart_name}", f"@capture('graph')\ndef {self.chart_name}")
            if chart_name is not None:
                chart_code = chart_code.replace(f"def {self.chart_name}", f"def {chart_name}")
            return chart_code
    
        def get_dashboard_template(self, data_info: DFMetaData) -> str:
            """Create a simple dashboard template for displaying the chart.
    
            Args:
                data_info: The metadata of the dataset to use.
    
            Returns:
                Complete Python code for a Vizro dashboard displaying the chart.
            """
            chart_code = self.get_chart_code(vizro=True)
            imports = self.get_imports(vizro=True)
    
            # Add the Vizro-specific imports if not present
            additional_dashboard_imports = [
                "import vizro.models as vm",
                "from vizro import Vizro",
                "from vizro.managers import data_manager",
            ]
    
            # Combine imports without duplicates
            all_imports = list(dict.fromkeys(additional_dashboard_imports + imports.split("\n")))
    
            dashboard_template = f"""
    {chr(10).join(imp for imp in all_imports if imp)}
    
    # Load the data
    data_manager["{data_info.file_name}"] = {data_info.read_function_string}("{data_info.file_path_or_url}")
    
    
    # Custom chart code
    {chart_code}
    
    # Create a dashboard to display the chart
    dashboard = vm.Dashboard(
        pages=[
            vm.Page(
                title="{self.chart_type.capitalize()} Chart",
                components=[
                    vm.Graph(
                        id="{self.chart_type}_graph",
                        figure={self.chart_name}("{data_info.file_name}"),
                    )
                ],
            )
        ],
        title="{self.chart_type.capitalize()} Dashboard",
    )
    
    # Run the dashboard
    Vizro().build(dashboard).run()
    """
    
            return dashboard_template

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/mckinsey/vizro'

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