Skip to main content
Glama
MR901

mcp-plots

render_chart

Create charts from tabular data using various visualization types like line, bar, and pie charts, with options for data analysis suggestions and format customization.

Instructions

    Render a chart from tabular data and return MCP-compatible content.
    
    Special modes:
    - chart_type="help": Returns available chart types, themes, and field suggestions
    - chart_type="suggest": Analyzes your data and suggests field mappings (requires data)

    Parameters:
    - chart_type: chart type ("line", "bar", "pie", etc.) or "help"/"suggest"
    - data: list of objects (rows) - optional for help mode
    - field_map: keys like x_field, y_field, category_field, value_field, group_field, size_field
    - config_overrides: subset of ChartConfig as dict (width, height, title, theme, dpi, etc.)
    - options: generator-specific options (e.g., smooth, stack)
    - output_format: MCP_IMAGE (PNG), MCP_TEXT (SVG), or MERMAID
    

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
chart_typeYes
dataNo
field_mapNo
config_overridesNo
optionsNo
output_formatNo

Implementation Reference

  • Registration of the 'render_chart' MCP tool with parameter schema and delegation to implementation.
    @mcp_server.tool()
    def render_chart(
        chart_type: str,
        data: List[Dict[str, Any]] = None,
        field_map: Dict[str, str] = None,
        config_overrides: Dict[str, Any] = None,
        options: Dict[str, Any] = None,
        output_format: str = None
    ) -> Dict[str, Any]:
        """
        Render a chart from tabular data and return MCP-compatible content.
        
        Special modes:
        - chart_type="help": Returns available chart types, themes, and field suggestions
        - chart_type="suggest": Analyzes your data and suggests field mappings (requires data)
    
        Parameters:
        - chart_type: chart type ("line", "bar", "pie", etc.) or "help"/"suggest"
        - data: list of objects (rows) - optional for help mode
        - field_map: keys like x_field, y_field, category_field, value_field, group_field, size_field
        - config_overrides: subset of ChartConfig as dict (width, height, title, theme, dpi, etc.)
        - options: generator-specific options (e.g., smooth, stack)
        - output_format: MCP_IMAGE (PNG), MCP_TEXT (SVG), or MERMAID
        """
        return _render_chart_impl(
            chart_type=chart_type,
            data=data,
            field_map=field_map,
            config_overrides=config_overrides,
            options=options,
            output_format=output_format
        )
  • Primary handler implementation that converts tool arguments to ChartRequest, invokes the chart rendering service, and formats the MCP response.
    def _render_chart_impl(
        chart_type: str,
        data: List[Dict[str, Any]] = None,
        field_map: Dict[str, str] = None,
        config_overrides: Dict[str, Any] = None,
        options: Dict[str, Any] = None,
        output_format: str = None
    ) -> Dict[str, Any]:
        """
        Render a chart from tabular data and return MCP-compatible content.
        
        Special modes:
        - chart_type="help": Returns available chart types, themes, and field suggestions
        - chart_type="suggest": Analyzes your data and suggests field mappings (requires data)
    
        Parameters:
        - chart_type: chart type ("line", "bar", "pie", etc.) or "help"/"suggest"
        - data: list of objects (rows) - optional for help mode
        - field_map: keys like x_field, y_field, category_field, value_field, group_field, size_field
        - config_overrides: subset of ChartConfig as dict (width, height, title, theme, dpi, etc.)
        - options: generator-specific options (e.g., smooth, stack)
        - output_format: MCP_IMAGE (PNG), MCP_TEXT (SVG), or MERMAID
        """
        try:
            # Create chart request from parameters
            request = ChartRequest.from_tool_params(
                chart_type=chart_type,
                data=data,
                field_map=field_map,
                config_overrides=config_overrides,
                options=options,
                output_format=output_format
            )
            
            # Use chart service
            chart_service = _get_chart_service()
            response = chart_service.render_chart(request)
            
            # Convert to MCP format
            return response.to_mcp_format()
            
        except Exception as e:
            logger.error(f"render_chart failed: {e}")
            return {"status": "error", "error": str(e)}
  • Dataclass defining the input schema for chart requests, including factory method from_tool_params that maps MCP tool parameters, validation, and field mapping.
    class ChartRequest:
        """
        Complete chart generation request with validation.
        
        Encapsulates all information needed to generate a chart,
        including data, configuration, and output preferences.
        """
        chart_type: str
        data: List[Dict[str, Any]]
        field_mapping: FieldMapping = field(default_factory=FieldMapping)
        config_overrides: Dict[str, Any] = field(default_factory=dict)
        options: Dict[str, Any] = field(default_factory=dict)
        output_format: Optional[str] = None
        mode: ChartRequestMode = ChartRequestMode.RENDER
        
        def __post_init__(self):
            """Validate request after initialization"""
            # Only validate for render mode, not for help/suggest
            if self.mode == ChartRequestMode.RENDER:
                self.validate()
        
        @classmethod
        def from_tool_params(
            cls,
            chart_type: str,
            data: Optional[List[Dict[str, Any]]] = None,
            field_map: Optional[Dict[str, str]] = None,
            config_overrides: Optional[Dict[str, Any]] = None,
            options: Optional[Dict[str, Any]] = None,
            output_format: Optional[str] = None
        ) -> 'ChartRequest':
            """Create request from MCP tool parameters"""
            
            # Determine mode based on chart_type
            if chart_type == "help":
                mode = ChartRequestMode.HELP
            elif chart_type == "suggest":
                mode = ChartRequestMode.SUGGEST
            else:
                mode = ChartRequestMode.RENDER
            
            return cls(
                chart_type=chart_type,
                data=data or [],
                field_mapping=FieldMapping.from_dict(field_map or {}),
                config_overrides=config_overrides or {},
                options=options or {},
                output_format=output_format,
                mode=mode
            )
        
        def validate(self) -> None:
            """Validate request for chart generation"""
            if self.mode == ChartRequestMode.RENDER:
                if not self.data:
                    raise ValueError(ChartConstants.ErrorMessages.EMPTY_DATA)
                
                if not isinstance(self.data, list):
                    raise ValueError(ChartConstants.ErrorMessages.INVALID_DATA_TYPE)
                
                if len(self.data) > ChartConstants.ConfigDefaults.MAX_DATA_POINTS:
                    raise ValueError(f"Data exceeds maximum allowed points: {ChartConstants.ConfigDefaults.MAX_DATA_POINTS}")
            
            elif self.mode == ChartRequestMode.SUGGEST:
                if not self.data:
                    raise ValueError("Data is required for field suggestions")
        
        def get_field_kwargs(self) -> Dict[str, Any]:
            """Get field mappings as kwargs for ChartGenerator"""
            return self.field_mapping.get_non_none_fields()
        
        def is_special_mode(self) -> bool:
            """Check if this is a special mode request (help/suggest)"""
            return self.mode in (ChartRequestMode.HELP, ChartRequestMode.SUGGEST)
  • Core service method implementing the chart rendering logic: handles special modes, validation, config building, chart generation via factory, and response normalization.
    def render_chart(self, request: ChartRequest) -> ChartResponse:
        """
        Render chart with full error handling and configuration management.
        
        Args:
            request: Complete chart rendering request
            
        Returns:
            ChartResponse: Standardized response with content or error
        """
        try:
            # Handle special modes
            if request.mode == ChartRequestMode.HELP:
                return self._generate_help_response()
            
            if request.mode == ChartRequestMode.SUGGEST:
                return self._generate_field_suggestions(request.data)
            
            # Validate request for regular chart rendering
            request.validate()
            
            # Get user preferences
            user_prefs = self._config_service.get_user_preferences()
            
            # Build chart configuration
            config = self._build_chart_config(request, user_prefs)
            
            # Build chart data
            chart_data = self._build_chart_data(request)
            
            # Generate chart using factory
            result = self._chart_factory.generate_chart(
                request.chart_type,
                chart_data=chart_data,
                config=config,
                **request.options
            )
            
            # Normalize response
            content = self._normalize_chart_result(result)
            
            return ChartResponse.success_response(
                content=content,
                metadata={
                    "chart_type": request.chart_type,
                    "data_points": len(request.data),
                    "output_format": config.output_format.value,
                    "generation_time": datetime.now().isoformat()
                }
            )
            
        except Exception as e:
            # Use centralized error handling
            error_response = ErrorHandler.handle_chart_error(e, getattr(request, 'chart_type', None))
            
            # Log the error with appropriate level
            if isinstance(e, ChartGenerationError):
                self._logger.warning(f"Chart generation error: {e}")
            else:
                self._logger.error(f"Unexpected chart rendering error: {e}")
            
            return ChartResponse.error_response(
                error=error_response["error"],
                metadata={
                    "chart_type": getattr(request, 'chart_type', 'unknown'),
                    "error_code": error_response.get("error_code", "UNKNOWN_ERROR"),
                    "error_type": type(e).__name__
                }
            )
  • Output response schema with MCP formatting method used by the handler.
    @dataclass
    class ChartResponse:
        """
        Standardized chart generation response.
        
        Provides consistent response format for all chart generation
        operations, including success and error cases.
        """
        success: bool
        content: Optional[List[Dict[str, Any]]] = None
        error: Optional[str] = None
        metadata: Dict[str, Any] = field(default_factory=dict)
        
        @classmethod
        def success_response(
            cls, 
            content: List[Dict[str, Any]], 
            metadata: Optional[Dict[str, Any]] = None
        ) -> 'ChartResponse':
            """Create successful response"""
            return cls(
                success=True,
                content=content,
                metadata=metadata or {}
            )
        
        @classmethod
        def error_response(cls, error: str, metadata: Optional[Dict[str, Any]] = None) -> 'ChartResponse':
            """Create error response"""
            return cls(
                success=False,
                error=error,
                metadata=metadata or {}
            )
        
        def to_mcp_format(self) -> Dict[str, Any]:
            """Convert to MCP tool response format"""
            if self.success:
                result = {"status": "success"}
                if self.content:
                    result["content"] = self.content
                return result
            else:
                return {
                    "status": "error",
                    "error": self.error or "Unknown error"
                }
        
        def to_dict(self) -> Dict[str, Any]:
            """Convert to dictionary for serialization"""
            return {
                "success": self.success,
                "content": self.content,
                "error": self.error,
                "metadata": self.metadata
            }
Install Server

Other Tools

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/MR901/mcp-plots'

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