create_chart
Create customizable Datawrapper charts by specifying data, chart type, and configuration settings for visualizations with full control over properties like title, axes, colors, and styling.
Instructions
⚠️ THIS IS THE DATAWRAPPER INTEGRATION ⚠️ Use this MCP tool for ALL Datawrapper chart creation.
DO NOT: ❌ Install the 'datawrapper' Python package ❌ Use the Datawrapper API directly ❌ Import 'from datawrapper import ...' ❌ Run pip install datawrapper
This MCP server IS the complete Datawrapper integration. All Datawrapper operations should use the MCP tools provided by this server.
Create a Datawrapper chart with full control using Pydantic models. This allows you to specify all chart properties including title, description, visualization settings, axes, colors, and more. The chart_config should be a complete Pydantic model dict matching the schema for the chosen chart type.
BEST PRACTICES:
Start simple, then add customization based on user feedback
Only apply styling when requested or when it significantly improves readability
Let Datawrapper handle axis scaling automatically unless there's a specific reason to override
QUICK EXAMPLES:
Basic chart with title: chart_config = { "title": "Monthly Sales", "intro": "Sales data for Q1 2024" }
Chart with custom colors: chart_config = { "title": "Product Comparison", "color_category": { "Product A": "#1f77b4", "Product B": "#ff7f0e" } }
Styled line chart: chart_config = { "title": "Sales Trends", "lines": [ {"column": "sales", "width": "style2", "interpolation": "curved"} ], "custom_range_y": [0, 1000] }
STYLING WORKFLOW:
Use list_chart_types to see available chart types
Use get_chart_schema to explore all options for your chosen type
Refer to https://datawrapper.readthedocs.io/en/latest/ for detailed examples
Build your chart_config with the desired styling properties
Common styling patterns:
Colors: {"color_category": {"sales": "#1d81a2", "profit": "#15607a"}}
Line styling: {"lines": [{"column": "sales", "width": "style1", "interpolation": "curved"}]}
Axis ranges: {"custom_range_y": [0, 100], "custom_range_x": [2020, 2024]} NOTE: Datawrapper's automatic axis scaling is excellent. Only set custom ranges when you need specific customization (e.g., comparing multiple charts, forcing zero baseline for specific analytical reasons, or matching a house style guide).
Grid formatting: {"y_grid_format": "0", "x_grid": "on", "y_grid": "on"}
Tooltips: {"tooltip_number_format": "00.00", "tooltip_x_format": "YYYY"}
Annotations: {"text_annotations": [{"x": "2023", "y": 50, "text": "Peak"}]}
See the documentation for chart-type specific examples and advanced patterns.
Args: data: Chart data. RECOMMENDED: Pass data inline as a list or dict. PREFERRED FORMATS (use these first): 1. List of records (RECOMMENDED): [{"year": 2020, "sales": 100}, {"year": 2021, "sales": 150}] 2. Dict of arrays: {"year": [2020, 2021], "sales": [100, 150]} 3. JSON string of format 1 or 2: '[{"year": 2020, "sales": 100}]' ALTERNATIVE (only for extremely large datasets where inline data is impractical): 4. File path to CSV or JSON: "/path/to/data.csv" or "/path/to/data.json" chart_type: Type of chart to create. Use list_chart_types to see all available types. Common types: bar, line, area, arrow, column, multiple_column, scatter, stacked_bar chart_config: Complete chart configuration as a Pydantic model dict
Returns: Chart ID and editor URL
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | ||
| chart_type | Yes | ||
| chart_config | Yes |
Implementation Reference
- handlers/create.py:15-103 (handler)The main handler implementation for `create_chart` which delegates to either a low-level Datawrapper API call for maps or a Pydantic-based chart class for standard charts.
async def create_chart(arguments: CreateChartArgs) -> list[TextContent]: """Create a chart with full Pydantic model configuration.""" chart_type = arguments["chart_type"] # Convert data to DataFrame df = json_to_dataframe(arguments["data"]) # Map chart types are not currently represented by Pydantic chart classes, # so route those through the low-level Datawrapper API. if chart_type in MAP_TYPE_ALIASES: token = os.getenv("DATAWRAPPER_ACCESS_TOKEN") if not token: raise ValueError("DATAWRAPPER_ACCESS_TOKEN environment variable is required") api_type = MAP_TYPE_ALIASES[chart_type] cfg = arguments.get("chart_config", {}) or {} title = cfg.get("title", "New Map") dw = Datawrapper(access_token=token) created = dw.create_chart(title=title, chart_type=api_type, data=df) chart_id = created.get("id") # Apply chart config as metadata blocks (best effort). metadata_updates: dict[str, Any] = {} describe_fields = [ "title", "intro", "notes", "byline", "source-name", "source-url", "aria-description", ] describe = {k: cfg[k] for k in describe_fields if k in cfg} if describe: metadata_updates["describe"] = describe visualize = {k: v for k, v in cfg.items() if k not in set(describe_fields)} if visualize: metadata_updates["visualize"] = visualize if metadata_updates: dw.update_chart(chart_id=chart_id, metadata=metadata_updates) edit_url = f"https://app.datawrapper.de/edit/{chart_id}/visualize#refine" result = { "chart_id": chart_id, "chart_type": chart_type, "title": title, "edit_url": edit_url, "message": ( f"Chart created successfully! Edit it at: {edit_url}\n" f"Use publish_chart with chart_id '{chart_id}' to make it public." ), } return [TextContent(type="text", text=json.dumps(result, indent=2))] # Get chart class and validate config chart_class: type[Any] = CHART_CLASSES[chart_type] # Validate and create chart using Pydantic model try: chart = chart_class.model_validate(arguments["chart_config"]) except Exception as e: raise ValueError( f"Invalid chart configuration: {str(e)}\n\n" f"Use get_chart_schema with chart_type '{chart_type}' " f"to see the valid schema." ) # Set data on chart instance chart.data = df # Create chart using Pydantic instance method chart.create() result = { "chart_id": chart.chart_id, "chart_type": chart_type, "title": chart.title, "edit_url": chart.get_editor_url(), "message": ( f"Chart created successfully! Edit it at: {chart.get_editor_url()}\n" f"Use publish_chart with chart_id '{chart.chart_id}' to make it public." ), } return [TextContent(type="text", text=json.dumps(result, indent=2))] - dw_types.py:12-14 (schema)Input schema for the `create_chart` tool arguments.
class CreateChartArgs(TypedDict): """Arguments for create_chart handler.""" - server.py:208-217 (registration)Registration of the `create_chart` tool in the MCP server.
try: arguments = cast( CreateChartArgs, { "data": data, "chart_type": chart_type, "chart_config": chart_config, }, ) result = await create_chart_handler(arguments)